1 | // Tests that depend on a count of the number of times their filter is evaluated |
2 | // cant exist in the same file with other tests that add subscribers to the |
3 | // registry. The registry was changed so that each time a new dispatcher is |
4 | // added all filters are re-evaluated. The tests being run only in separate |
5 | // threads with shared global state lets them interfere with each other |
6 | #[cfg (not(feature = "std" ))] |
7 | extern crate std; |
8 | |
9 | use tracing::{span, Level}; |
10 | use tracing_mock::*; |
11 | |
12 | use std::sync::{ |
13 | atomic::{AtomicUsize, Ordering}, |
14 | Arc, |
15 | }; |
16 | |
17 | #[cfg_attr (target_arch = "wasm32" , wasm_bindgen_test::wasm_bindgen_test)] |
18 | #[test] |
19 | fn filters_are_reevaluated_for_different_call_sites() { |
20 | // Asserts that the `span!` macro caches the result of calling |
21 | // `Subscriber::enabled` for each span. |
22 | let charlie_count = Arc::new(AtomicUsize::new(0)); |
23 | let dave_count = Arc::new(AtomicUsize::new(0)); |
24 | let charlie_count2 = charlie_count.clone(); |
25 | let dave_count2 = dave_count.clone(); |
26 | |
27 | let subscriber = subscriber::mock() |
28 | .with_filter(move |meta| { |
29 | println!("Filter: {:?}" , meta.name()); |
30 | match meta.name() { |
31 | "charlie" => { |
32 | charlie_count2.fetch_add(1, Ordering::Relaxed); |
33 | false |
34 | } |
35 | "dave" => { |
36 | dave_count2.fetch_add(1, Ordering::Relaxed); |
37 | true |
38 | } |
39 | _ => false, |
40 | } |
41 | }) |
42 | .run(); |
43 | |
44 | // Since this test is in its own file anyway, we can do this. Thus, this |
45 | // test will work even with no-std. |
46 | tracing::subscriber::set_global_default(subscriber).unwrap(); |
47 | |
48 | // Enter "charlie" and then "dave". The dispatcher expects to see "dave" but |
49 | // not "charlie." |
50 | let charlie = span!(Level::TRACE, "charlie" ); |
51 | let dave = charlie.in_scope(|| { |
52 | let dave = span!(Level::TRACE, "dave" ); |
53 | dave.in_scope(|| {}); |
54 | dave |
55 | }); |
56 | |
57 | // The filter should have seen each span a single time. |
58 | assert_eq!(charlie_count.load(Ordering::Relaxed), 1); |
59 | assert_eq!(dave_count.load(Ordering::Relaxed), 1); |
60 | |
61 | charlie.in_scope(|| dave.in_scope(|| {})); |
62 | |
63 | // The subscriber should see "dave" again, but the filter should not have |
64 | // been called. |
65 | assert_eq!(charlie_count.load(Ordering::Relaxed), 1); |
66 | assert_eq!(dave_count.load(Ordering::Relaxed), 1); |
67 | |
68 | // A different span with the same name has a different call site, so it |
69 | // should cause the filter to be reapplied. |
70 | let charlie2 = span!(Level::TRACE, "charlie" ); |
71 | charlie.in_scope(|| {}); |
72 | assert_eq!(charlie_count.load(Ordering::Relaxed), 2); |
73 | assert_eq!(dave_count.load(Ordering::Relaxed), 1); |
74 | |
75 | // But, the filter should not be re-evaluated for the new "charlie" span |
76 | // when it is re-entered. |
77 | charlie2.in_scope(|| span!(Level::TRACE, "dave" ).in_scope(|| {})); |
78 | assert_eq!(charlie_count.load(Ordering::Relaxed), 2); |
79 | assert_eq!(dave_count.load(Ordering::Relaxed), 2); |
80 | } |
81 | |