• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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