1 use super::*;
2 use tracing_core::subscriber::NoSubscriber;
3
4 #[derive(Debug)]
5 pub(crate) struct NopLayer;
6 impl<S: Subscriber> Layer<S> for NopLayer {}
7
8 #[allow(dead_code)]
9 struct NopLayer2;
10 impl<S: Subscriber> Layer<S> for NopLayer2 {}
11
12 /// A layer that holds a string.
13 ///
14 /// Used to test that pointers returned by downcasting are actually valid.
15 struct StringLayer(&'static str);
16 impl<S: Subscriber> Layer<S> for StringLayer {}
17 struct StringLayer2(&'static str);
18 impl<S: Subscriber> Layer<S> for StringLayer2 {}
19
20 struct StringLayer3(&'static str);
21 impl<S: Subscriber> Layer<S> for StringLayer3 {}
22
23 pub(crate) struct StringSubscriber(&'static str);
24
25 impl Subscriber for StringSubscriber {
register_callsite(&self, _: &'static Metadata<'static>) -> Interest26 fn register_callsite(&self, _: &'static Metadata<'static>) -> Interest {
27 Interest::never()
28 }
29
enabled(&self, _: &Metadata<'_>) -> bool30 fn enabled(&self, _: &Metadata<'_>) -> bool {
31 false
32 }
33
new_span(&self, _: &span::Attributes<'_>) -> span::Id34 fn new_span(&self, _: &span::Attributes<'_>) -> span::Id {
35 span::Id::from_u64(1)
36 }
37
record(&self, _: &span::Id, _: &span::Record<'_>)38 fn record(&self, _: &span::Id, _: &span::Record<'_>) {}
record_follows_from(&self, _: &span::Id, _: &span::Id)39 fn record_follows_from(&self, _: &span::Id, _: &span::Id) {}
event(&self, _: &Event<'_>)40 fn event(&self, _: &Event<'_>) {}
enter(&self, _: &span::Id)41 fn enter(&self, _: &span::Id) {}
exit(&self, _: &span::Id)42 fn exit(&self, _: &span::Id) {}
43 }
44
assert_subscriber(_s: impl Subscriber)45 fn assert_subscriber(_s: impl Subscriber) {}
assert_layer<S: Subscriber>(_l: &impl Layer<S>)46 fn assert_layer<S: Subscriber>(_l: &impl Layer<S>) {}
47
48 #[test]
layer_is_subscriber()49 fn layer_is_subscriber() {
50 let s = NopLayer.with_subscriber(NoSubscriber::default());
51 assert_subscriber(s)
52 }
53
54 #[test]
two_layers_are_subscriber()55 fn two_layers_are_subscriber() {
56 let s = NopLayer
57 .and_then(NopLayer)
58 .with_subscriber(NoSubscriber::default());
59 assert_subscriber(s)
60 }
61
62 #[test]
three_layers_are_subscriber()63 fn three_layers_are_subscriber() {
64 let s = NopLayer
65 .and_then(NopLayer)
66 .and_then(NopLayer)
67 .with_subscriber(NoSubscriber::default());
68 assert_subscriber(s)
69 }
70
71 #[test]
three_layers_are_layer()72 fn three_layers_are_layer() {
73 let layers = NopLayer.and_then(NopLayer).and_then(NopLayer);
74 assert_layer(&layers);
75 let _ = layers.with_subscriber(NoSubscriber::default());
76 }
77
78 #[test]
79 #[cfg(feature = "alloc")]
box_layer_is_layer()80 fn box_layer_is_layer() {
81 use alloc::boxed::Box;
82 let l: Box<dyn Layer<NoSubscriber> + Send + Sync> = Box::new(NopLayer);
83 assert_layer(&l);
84 l.with_subscriber(NoSubscriber::default());
85 }
86
87 #[test]
downcasts_to_subscriber()88 fn downcasts_to_subscriber() {
89 let s = NopLayer
90 .and_then(NopLayer)
91 .and_then(NopLayer)
92 .with_subscriber(StringSubscriber("subscriber"));
93 let subscriber =
94 <dyn Subscriber>::downcast_ref::<StringSubscriber>(&s).expect("subscriber should downcast");
95 assert_eq!(subscriber.0, "subscriber");
96 }
97
98 #[test]
downcasts_to_layer()99 fn downcasts_to_layer() {
100 let s = StringLayer("layer_1")
101 .and_then(StringLayer2("layer_2"))
102 .and_then(StringLayer3("layer_3"))
103 .with_subscriber(NoSubscriber::default());
104 let layer = <dyn Subscriber>::downcast_ref::<StringLayer>(&s).expect("layer 1 should downcast");
105 assert_eq!(layer.0, "layer_1");
106 let layer =
107 <dyn Subscriber>::downcast_ref::<StringLayer2>(&s).expect("layer 2 should downcast");
108 assert_eq!(layer.0, "layer_2");
109 let layer =
110 <dyn Subscriber>::downcast_ref::<StringLayer3>(&s).expect("layer 3 should downcast");
111 assert_eq!(layer.0, "layer_3");
112 }
113
114 #[cfg(all(feature = "registry", feature = "std"))]
115 mod registry_tests {
116 use super::*;
117 use crate::registry::LookupSpan;
118
119 #[test]
context_event_span()120 fn context_event_span() {
121 use std::sync::{Arc, Mutex};
122 let last_event_span = Arc::new(Mutex::new(None));
123
124 struct RecordingLayer {
125 last_event_span: Arc<Mutex<Option<&'static str>>>,
126 }
127
128 impl<S> Layer<S> for RecordingLayer
129 where
130 S: Subscriber + for<'lookup> LookupSpan<'lookup>,
131 {
132 fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
133 let span = ctx.event_span(event);
134 *self.last_event_span.lock().unwrap() = span.map(|s| s.name());
135 }
136 }
137
138 tracing::subscriber::with_default(
139 crate::registry().with(RecordingLayer {
140 last_event_span: last_event_span.clone(),
141 }),
142 || {
143 tracing::info!("no span");
144 assert_eq!(*last_event_span.lock().unwrap(), None);
145
146 let parent = tracing::info_span!("explicit");
147 tracing::info!(parent: &parent, "explicit span");
148 assert_eq!(*last_event_span.lock().unwrap(), Some("explicit"));
149
150 let _guard = tracing::info_span!("contextual").entered();
151 tracing::info!("contextual span");
152 assert_eq!(*last_event_span.lock().unwrap(), Some("contextual"));
153 },
154 );
155 }
156
157 /// Tests for how max-level hints are calculated when combining layers
158 /// with and without per-layer filtering.
159 mod max_level_hints {
160
161 use super::*;
162 use crate::filter::*;
163
164 #[test]
mixed_with_unfiltered()165 fn mixed_with_unfiltered() {
166 let subscriber = crate::registry()
167 .with(NopLayer)
168 .with(NopLayer.with_filter(LevelFilter::INFO));
169 assert_eq!(subscriber.max_level_hint(), None);
170 }
171
172 #[test]
mixed_with_unfiltered_layered()173 fn mixed_with_unfiltered_layered() {
174 let subscriber = crate::registry().with(NopLayer).with(
175 NopLayer
176 .with_filter(LevelFilter::INFO)
177 .and_then(NopLayer.with_filter(LevelFilter::TRACE)),
178 );
179 assert_eq!(dbg!(subscriber).max_level_hint(), None);
180 }
181
182 #[test]
mixed_interleaved()183 fn mixed_interleaved() {
184 let subscriber = crate::registry()
185 .with(NopLayer)
186 .with(NopLayer.with_filter(LevelFilter::INFO))
187 .with(NopLayer)
188 .with(NopLayer.with_filter(LevelFilter::INFO));
189 assert_eq!(dbg!(subscriber).max_level_hint(), None);
190 }
191
192 #[test]
mixed_layered()193 fn mixed_layered() {
194 let subscriber = crate::registry()
195 .with(NopLayer.with_filter(LevelFilter::INFO).and_then(NopLayer))
196 .with(NopLayer.and_then(NopLayer.with_filter(LevelFilter::INFO)));
197 assert_eq!(dbg!(subscriber).max_level_hint(), None);
198 }
199
200 #[test]
plf_only_unhinted()201 fn plf_only_unhinted() {
202 let subscriber = crate::registry()
203 .with(NopLayer.with_filter(LevelFilter::INFO))
204 .with(NopLayer.with_filter(filter_fn(|_| true)));
205 assert_eq!(dbg!(subscriber).max_level_hint(), None);
206 }
207
208 #[test]
plf_only_unhinted_nested_outer()209 fn plf_only_unhinted_nested_outer() {
210 // if a nested tree of per-layer filters has an _outer_ filter with
211 // no max level hint, it should return `None`.
212 let subscriber = crate::registry()
213 .with(
214 NopLayer
215 .with_filter(LevelFilter::INFO)
216 .and_then(NopLayer.with_filter(LevelFilter::WARN)),
217 )
218 .with(
219 NopLayer
220 .with_filter(filter_fn(|_| true))
221 .and_then(NopLayer.with_filter(LevelFilter::DEBUG)),
222 );
223 assert_eq!(dbg!(subscriber).max_level_hint(), None);
224 }
225
226 #[test]
plf_only_unhinted_nested_inner()227 fn plf_only_unhinted_nested_inner() {
228 // If a nested tree of per-layer filters has an _inner_ filter with
229 // no max-level hint, but the _outer_ filter has a max level hint,
230 // it should pick the outer hint. This is because the outer filter
231 // will disable the spans/events before they make it to the inner
232 // filter.
233 let subscriber = dbg!(crate::registry().with(
234 NopLayer
235 .with_filter(filter_fn(|_| true))
236 .and_then(NopLayer.with_filter(filter_fn(|_| true)))
237 .with_filter(LevelFilter::INFO),
238 ));
239 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO));
240 }
241
242 #[test]
unhinted_nested_inner()243 fn unhinted_nested_inner() {
244 let subscriber = dbg!(crate::registry()
245 .with(NopLayer.and_then(NopLayer).with_filter(LevelFilter::INFO))
246 .with(
247 NopLayer
248 .with_filter(filter_fn(|_| true))
249 .and_then(NopLayer.with_filter(filter_fn(|_| true)))
250 .with_filter(LevelFilter::WARN),
251 ));
252 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO));
253 }
254
255 #[test]
unhinted_nested_inner_mixed()256 fn unhinted_nested_inner_mixed() {
257 let subscriber = dbg!(crate::registry()
258 .with(
259 NopLayer
260 .and_then(NopLayer.with_filter(filter_fn(|_| true)))
261 .with_filter(LevelFilter::INFO)
262 )
263 .with(
264 NopLayer
265 .with_filter(filter_fn(|_| true))
266 .and_then(NopLayer.with_filter(filter_fn(|_| true)))
267 .with_filter(LevelFilter::WARN),
268 ));
269 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::INFO));
270 }
271
272 #[test]
plf_only_picks_max()273 fn plf_only_picks_max() {
274 let subscriber = crate::registry()
275 .with(NopLayer.with_filter(LevelFilter::WARN))
276 .with(NopLayer.with_filter(LevelFilter::DEBUG));
277 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG));
278 }
279
280 #[test]
many_plf_only_picks_max()281 fn many_plf_only_picks_max() {
282 let subscriber = crate::registry()
283 .with(NopLayer.with_filter(LevelFilter::WARN))
284 .with(NopLayer.with_filter(LevelFilter::DEBUG))
285 .with(NopLayer.with_filter(LevelFilter::INFO))
286 .with(NopLayer.with_filter(LevelFilter::ERROR));
287 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG));
288 }
289
290 #[test]
nested_plf_only_picks_max()291 fn nested_plf_only_picks_max() {
292 let subscriber = crate::registry()
293 .with(
294 NopLayer.with_filter(LevelFilter::INFO).and_then(
295 NopLayer
296 .with_filter(LevelFilter::WARN)
297 .and_then(NopLayer.with_filter(LevelFilter::DEBUG)),
298 ),
299 )
300 .with(
301 NopLayer
302 .with_filter(LevelFilter::INFO)
303 .and_then(NopLayer.with_filter(LevelFilter::ERROR)),
304 );
305 assert_eq!(dbg!(subscriber).max_level_hint(), Some(LevelFilter::DEBUG));
306 }
307 }
308 }
309