1#![cfg(feature = "registry")]
2use std::{
3 collections::HashMap,
4 sync::{Arc, Mutex},
5};
6use tracing::{Level, Subscriber};
7use tracing_mock::{expect, layer};
8use tracing_subscriber::{filter, prelude::*};
9
10#[test]
11fn multiple_layer_filter_interests_are_cached() {
12 // This layer will return Interest::always for INFO and lower.
13 let seen_info = Arc::new(Mutex::new(HashMap::new()));
14 let seen_info2 = seen_info.clone();
15 let filter = filter::filter_fn(move |meta| {
16 *seen_info
17 .lock()
18 .unwrap()
19 .entry(*meta.level())
20 .or_insert(0usize) += 1;
21 meta.level() <= &Level::INFO
22 });
23 let seen_info = seen_info2;
24
25 let (info_layer, info_handle) = layer::named("info")
26 .event(expect::event().at_level(Level::INFO))
27 .event(expect::event().at_level(Level::WARN))
28 .event(expect::event().at_level(Level::ERROR))
29 .event(expect::event().at_level(Level::INFO))
30 .event(expect::event().at_level(Level::WARN))
31 .event(expect::event().at_level(Level::ERROR))
32 .only()
33 .run_with_handle();
34 let info_layer = info_layer.with_filter(filter);
35
36 // This layer will return Interest::always for WARN and lower.
37 let seen_warn = Arc::new(Mutex::new(HashMap::new()));
38 let seen_warn2 = seen_warn.clone();
39 let filter = filter::filter_fn(move |meta| {
40 *seen_warn
41 .lock()
42 .unwrap()
43 .entry(*meta.level())
44 .or_insert(0usize) += 1;
45 meta.level() <= &Level::WARN
46 });
47 let seen_warn = seen_warn2;
48
49 let (warn_layer, warn_handle) = layer::named("warn")
50 .event(expect::event().at_level(Level::WARN))
51 .event(expect::event().at_level(Level::ERROR))
52 .event(expect::event().at_level(Level::WARN))
53 .event(expect::event().at_level(Level::ERROR))
54 .only()
55 .run_with_handle();
56 let warn_layer = warn_layer.with_filter(filter);
57
58 let subscriber = tracing_subscriber::registry()
59 .with(warn_layer)
60 .with(info_layer);
61 assert!(subscriber.max_level_hint().is_none());
62
63 let _subscriber = subscriber.set_default();
64
65 fn events() {
66 tracing::trace!("hello trace");
67 tracing::debug!("hello debug");
68 tracing::info!("hello info");
69 tracing::warn!("hello warn");
70 tracing::error!("hello error");
71 }
72
73 events();
74 {
75 let lock = seen_info.lock().unwrap();
76 for (&level, &count) in lock.iter() {
77 if level == Level::INFO {
78 continue;
79 }
80 assert_eq!(
81 count, 1,
82 "level {:?} should have been seen 1 time by the INFO layer (after first set of events)",
83 level
84 );
85 }
86
87 let lock = seen_warn.lock().unwrap();
88 for (&level, &count) in lock.iter() {
89 if level == Level::INFO {
90 continue;
91 }
92 assert_eq!(
93 count, 1,
94 "level {:?} should have been seen 1 time by the WARN layer (after first set of events)",
95 level
96 );
97 }
98 }
99
100 events();
101 {
102 let lock = seen_info.lock().unwrap();
103 for (&level, &count) in lock.iter() {
104 if level == Level::INFO {
105 continue;
106 }
107 assert_eq!(
108 count, 1,
109 "level {:?} should have been seen 1 time by the INFO layer (after second set of events)",
110 level
111 );
112 }
113
114 let lock = seen_warn.lock().unwrap();
115 for (&level, &count) in lock.iter() {
116 if level == Level::INFO {
117 continue;
118 }
119 assert_eq!(
120 count, 1,
121 "level {:?} should have been seen 1 time by the WARN layer (after second set of events)",
122 level
123 );
124 }
125 }
126
127 info_handle.assert_finished();
128 warn_handle.assert_finished();
129}
130