1#![cfg(feature = "registry")]
2use tracing_core::{subscriber::Interest, LevelFilter, Metadata, Subscriber};
3use tracing_subscriber::{layer, prelude::*};
4
5// A basic layer that returns its inner for `max_level_hint`
6#[derive(Debug)]
7struct BasicLayer(Option<LevelFilter>);
8impl<S: Subscriber> tracing_subscriber::Layer<S> for BasicLayer {
9 fn register_callsite(&self, _m: &Metadata<'_>) -> Interest {
10 Interest::sometimes()
11 }
12
13 fn enabled(&self, _m: &Metadata<'_>, _: layer::Context<'_, S>) -> bool {
14 true
15 }
16
17 fn max_level_hint(&self) -> Option<LevelFilter> {
18 self.0
19 }
20}
21
22// This test is just used to compare to the tests below
23#[test]
24fn just_layer() {
25 let subscriber = tracing_subscriber::registry().with(LevelFilter::INFO);
26 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::INFO));
27}
28
29#[test]
30fn subscriber_and_option_some_layer() {
31 let subscriber = tracing_subscriber::registry()
32 .with(LevelFilter::INFO)
33 .with(Some(LevelFilter::DEBUG));
34 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
35}
36
37#[test]
38fn subscriber_and_option_none_layer() {
39 // None means the other layer takes control
40 let subscriber = tracing_subscriber::registry()
41 .with(LevelFilter::ERROR)
42 .with(None::<LevelFilter>);
43 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));
44}
45
46#[test]
47fn just_option_some_layer() {
48 // Just a None means everything is off
49 let subscriber = tracing_subscriber::registry().with(None::<LevelFilter>);
50 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
51}
52
53/// Tests that the logic tested in `doesnt_override_none` works through the reload subscriber
54#[test]
55fn just_option_none_layer() {
56 let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR));
57 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));
58}
59
60// Test that the `None` max level hint only applies if its the only layer
61#[test]
62fn none_outside_doesnt_override_max_level() {
63 // None means the other layer takes control
64 let subscriber = tracing_subscriber::registry()
65 .with(BasicLayer(None))
66 .with(None::<LevelFilter>);
67 assert_eq!(
68 subscriber.max_level_hint(),
69 None,
70 "\n stack: {:#?}",
71 subscriber
72 );
73
74 // The `None`-returning layer still wins
75 let subscriber = tracing_subscriber::registry()
76 .with(BasicLayer(None))
77 .with(Some(LevelFilter::ERROR));
78 assert_eq!(
79 subscriber.max_level_hint(),
80 Some(LevelFilter::ERROR),
81 "\n stack: {:#?}",
82 subscriber
83 );
84
85 // Check that we aren't doing anything truly wrong
86 let subscriber = tracing_subscriber::registry()
87 .with(BasicLayer(Some(LevelFilter::DEBUG)))
88 .with(None::<LevelFilter>);
89 assert_eq!(
90 subscriber.max_level_hint(),
91 Some(LevelFilter::DEBUG),
92 "\n stack: {:#?}",
93 subscriber
94 );
95
96 // Test that per-subscriber filters aren't affected
97
98 // One layer is None so it "wins"
99 let subscriber = tracing_subscriber::registry()
100 .with(BasicLayer(None))
101 .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
102 assert_eq!(
103 subscriber.max_level_hint(),
104 None,
105 "\n stack: {:#?}",
106 subscriber
107 );
108
109 // The max-levels wins
110 let subscriber = tracing_subscriber::registry()
111 .with(BasicLayer(Some(LevelFilter::INFO)))
112 .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG));
113 assert_eq!(
114 subscriber.max_level_hint(),
115 Some(LevelFilter::DEBUG),
116 "\n stack: {:#?}",
117 subscriber
118 );
119
120 // Test filter on the other layer
121 let subscriber = tracing_subscriber::registry()
122 .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG))
123 .with(None::<LevelFilter>);
124 assert_eq!(
125 subscriber.max_level_hint(),
126 Some(LevelFilter::DEBUG),
127 "\n stack: {:#?}",
128 subscriber
129 );
130 let subscriber = tracing_subscriber::registry()
131 .with(BasicLayer(None).with_filter(LevelFilter::DEBUG))
132 .with(None::<LevelFilter>);
133 assert_eq!(
134 subscriber.max_level_hint(),
135 Some(LevelFilter::DEBUG),
136 "\n stack: {:#?}",
137 subscriber
138 );
139
140 // The `OFF` from `None` over overridden.
141 let subscriber = tracing_subscriber::registry()
142 .with(BasicLayer(Some(LevelFilter::INFO)))
143 .with(None::<LevelFilter>);
144 assert_eq!(
145 subscriber.max_level_hint(),
146 Some(LevelFilter::INFO),
147 "\n stack: {:#?}",
148 subscriber
149 );
150}
151
152// Test that the `None` max level hint only applies if its the only layer
153#[test]
154fn none_inside_doesnt_override_max_level() {
155 // None means the other layer takes control
156 let subscriber = tracing_subscriber::registry()
157 .with(None::<LevelFilter>)
158 .with(BasicLayer(None));
159 assert_eq!(
160 subscriber.max_level_hint(),
161 None,
162 "\n stack: {:#?}",
163 subscriber
164 );
165
166 // The `None`-returning layer still wins
167 let subscriber = tracing_subscriber::registry()
168 .with(Some(LevelFilter::ERROR))
169 .with(BasicLayer(None));
170 assert_eq!(
171 subscriber.max_level_hint(),
172 Some(LevelFilter::ERROR),
173 "\n stack: {:#?}",
174 subscriber
175 );
176
177 // Check that we aren't doing anything truly wrong
178 let subscriber = tracing_subscriber::registry()
179 .with(None::<LevelFilter>)
180 .with(BasicLayer(Some(LevelFilter::DEBUG)));
181 assert_eq!(
182 subscriber.max_level_hint(),
183 Some(LevelFilter::DEBUG),
184 "\n stack: {:#?}",
185 subscriber
186 );
187
188 // Test that per-subscriber filters aren't affected
189
190 // One layer is None so it "wins"
191 let subscriber = tracing_subscriber::registry()
192 .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG))
193 .with(BasicLayer(None));
194 assert_eq!(
195 subscriber.max_level_hint(),
196 None,
197 "\n stack: {:#?}",
198 subscriber
199 );
200
201 // The max-levels wins
202 let subscriber = tracing_subscriber::registry()
203 .with(None::<LevelFilter>.with_filter(LevelFilter::DEBUG))
204 .with(BasicLayer(Some(LevelFilter::INFO)));
205 assert_eq!(
206 subscriber.max_level_hint(),
207 Some(LevelFilter::DEBUG),
208 "\n stack: {:#?}",
209 subscriber
210 );
211
212 // Test filter on the other layer
213 let subscriber = tracing_subscriber::registry()
214 .with(None::<LevelFilter>)
215 .with(BasicLayer(Some(LevelFilter::INFO)).with_filter(LevelFilter::DEBUG));
216 assert_eq!(
217 subscriber.max_level_hint(),
218 Some(LevelFilter::DEBUG),
219 "\n stack: {:#?}",
220 subscriber
221 );
222 let subscriber = tracing_subscriber::registry()
223 .with(None::<LevelFilter>)
224 .with(BasicLayer(None).with_filter(LevelFilter::DEBUG));
225 assert_eq!(
226 subscriber.max_level_hint(),
227 Some(LevelFilter::DEBUG),
228 "\n stack: {:#?}",
229 subscriber
230 );
231
232 // The `OFF` from `None` over overridden.
233 let subscriber = tracing_subscriber::registry()
234 .with(None::<LevelFilter>)
235 .with(BasicLayer(Some(LevelFilter::INFO)));
236 assert_eq!(
237 subscriber.max_level_hint(),
238 Some(LevelFilter::INFO),
239 "\n stack: {:#?}",
240 subscriber
241 );
242}
243
244/// Tests that the logic tested in `doesnt_override_none` works through the reload layer
245#[test]
246fn reload_works_with_none() {
247 let (layer1, handle1) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>);
248 let (layer2, _handle2) = tracing_subscriber::reload::Layer::new(None::<BasicLayer>);
249
250 let subscriber = tracing_subscriber::registry().with(layer1).with(layer2);
251 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::OFF));
252
253 // reloading one should pass through correctly.
254 handle1.reload(Some(BasicLayer(None))).unwrap();
255 assert_eq!(subscriber.max_level_hint(), None);
256
257 // Check pass-through of an actual level as well
258 handle1
259 .reload(Some(BasicLayer(Some(LevelFilter::DEBUG))))
260 .unwrap();
261 assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::DEBUG));
262}
263