Skip to content

Commit c54aa4e

Browse files
authored
subscriber: increase EnvFilter test coverage (tokio-rs#3262)
1 parent dfc2c8b commit c54aa4e

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

tracing-subscriber/src/filter/env/builder.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ impl Builder {
133133

134134
/// Returns a new [`EnvFilter`] from the directives in the given string,
135135
/// *ignoring* any that are invalid.
136+
///
137+
/// If `parse_lossy` is called with an empty string, then the
138+
/// [default directive] is used instead.
139+
///
140+
/// [default directive]: Self::with_default_directive
136141
pub fn parse_lossy<S: AsRef<str>>(&self, dirs: S) -> EnvFilter {
137142
let directives = dirs
138143
.as_ref()
@@ -150,6 +155,11 @@ impl Builder {
150155

151156
/// Returns a new [`EnvFilter`] from the directives in the given string,
152157
/// or an error if any are invalid.
158+
///
159+
/// If `parse` is called with an empty string, then the [default directive]
160+
/// is used instead.
161+
///
162+
/// [default directive]: Self::with_default_directive
153163
pub fn parse<S: AsRef<str>>(&self, dirs: S) -> Result<EnvFilter, directive::ParseError> {
154164
let dirs = dirs.as_ref();
155165
if dirs.is_empty() {
@@ -165,6 +175,11 @@ impl Builder {
165175

166176
/// Returns a new [`EnvFilter`] from the directives in the configured
167177
/// environment variable, ignoring any directives that are invalid.
178+
///
179+
/// If the environment variable is empty, then the [default directive]
180+
/// is used instead.
181+
///
182+
/// [default directive]: Self::with_default_directive
168183
pub fn from_env_lossy(&self) -> EnvFilter {
169184
let var = env::var(self.env_var_name()).unwrap_or_default();
170185
self.parse_lossy(var)
@@ -174,6 +189,11 @@ impl Builder {
174189
/// environment variable. If the environment variable is unset, no directive is added.
175190
///
176191
/// An error is returned if the environment contains invalid directives.
192+
///
193+
/// If the environment variable is empty, then the [default directive]
194+
/// is used instead.
195+
///
196+
/// [default directive]: Self::with_default_directive
177197
pub fn from_env(&self) -> Result<EnvFilter, FromEnvError> {
178198
let var = env::var(self.env_var_name()).unwrap_or_default();
179199
self.parse(var).map_err(Into::into)
@@ -182,6 +202,11 @@ impl Builder {
182202
/// Returns a new [`EnvFilter`] from the directives in the configured
183203
/// environment variable, or an error if the environment variable is not set
184204
/// or contains invalid directives.
205+
///
206+
/// If the environment variable is empty, then the [default directive]
207+
/// is used instead.
208+
///
209+
/// [default directive]: Self::with_default_directive
185210
pub fn try_from_env(&self) -> Result<EnvFilter, FromEnvError> {
186211
let var = env::var(self.env_var_name())?;
187212
self.parse(var).map_err(Into::into)

tracing-subscriber/tests/env_filter/main.rs

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,3 +195,210 @@ fn method_name_resolution() {
195195
let filter = EnvFilter::new("hello_world=info");
196196
filter.max_level_hint();
197197
}
198+
199+
#[test]
200+
fn parse_invalid_string() {
201+
assert!(EnvFilter::builder().parse(",!").is_err());
202+
}
203+
204+
#[test]
205+
fn parse_empty_string_no_default_directive() {
206+
let filter = EnvFilter::builder().parse("").expect("filter should parse");
207+
let (collector, finished) = collector::mock().only().run_with_handle();
208+
let subscriber = collector.with(filter);
209+
210+
with_default(subscriber, || {
211+
tracing::trace!("this should be disabled");
212+
tracing::debug!("this should be disabled");
213+
tracing::info!("this should be disabled");
214+
tracing::warn!("this should be disabled");
215+
tracing::error!("this should be disabled");
216+
});
217+
218+
finished.assert_finished();
219+
}
220+
221+
#[test]
222+
fn parse_empty_string_with_default_directive() {
223+
let filter = EnvFilter::builder()
224+
.with_default_directive(LevelFilter::INFO.into())
225+
.parse("")
226+
.expect("filter should parse");
227+
let (collector, finished) = collector::mock()
228+
.event(expect::event().at_level(Level::INFO))
229+
.event(expect::event().at_level(Level::WARN))
230+
.event(expect::event().at_level(Level::ERROR))
231+
.only()
232+
.run_with_handle();
233+
let subscriber = collector.with(filter);
234+
235+
with_default(subscriber, || {
236+
tracing::trace!("this should be disabled");
237+
tracing::debug!("this should be disabled");
238+
tracing::info!("this shouldn't be disabled");
239+
tracing::warn!("this shouldn't be disabled");
240+
tracing::error!("this shouldn't be disabled");
241+
});
242+
243+
finished.assert_finished();
244+
}
245+
246+
#[test]
247+
fn new_invalid_string() {
248+
let filter = EnvFilter::new(",!");
249+
let (collector, finished) = collector::mock()
250+
.event(expect::event().at_level(Level::ERROR))
251+
.only()
252+
.run_with_handle();
253+
let subscriber = collector.with(filter);
254+
255+
with_default(subscriber, || {
256+
tracing::trace!("this should be disabled");
257+
tracing::debug!("this should be disabled");
258+
tracing::info!("this should be disabled");
259+
tracing::warn!("this should be disabled");
260+
tracing::error!("this shouldn't be disabled");
261+
});
262+
263+
finished.assert_finished();
264+
}
265+
266+
#[test]
267+
fn new_empty_string() {
268+
let filter = EnvFilter::new("");
269+
let (collector, finished) = collector::mock()
270+
.event(expect::event().at_level(Level::ERROR))
271+
.only()
272+
.run_with_handle();
273+
let subscriber = collector.with(filter);
274+
275+
with_default(subscriber, || {
276+
tracing::trace!("this should be disabled");
277+
tracing::debug!("this should be disabled");
278+
tracing::info!("this should be disabled");
279+
tracing::warn!("this should be disabled");
280+
tracing::error!("this shouldn't be disabled");
281+
});
282+
283+
finished.assert_finished();
284+
}
285+
286+
#[test]
287+
fn more_specific_static_filter_more_verbose() {
288+
let filter = EnvFilter::new("info,hello=debug");
289+
let (collector, finished) = collector::mock()
290+
.event(expect::event().at_level(Level::INFO))
291+
.event(expect::event().at_level(Level::DEBUG).with_target("hello"))
292+
.only()
293+
.run_with_handle();
294+
let subscriber = collector.with(filter);
295+
296+
with_default(subscriber, || {
297+
tracing::info!("should be enabled");
298+
tracing::debug!("should be disabled");
299+
tracing::debug!(target: "hello", "should be enabled");
300+
});
301+
302+
finished.assert_finished();
303+
}
304+
305+
#[test]
306+
fn more_specific_static_filter_less_verbose() {
307+
let filter = EnvFilter::new("info,hello=warn");
308+
let (collector, finished) = collector::mock()
309+
.event(expect::event().at_level(Level::INFO))
310+
.event(
311+
expect::event()
312+
.at_level(Level::WARN)
313+
.with_target("env_filter"),
314+
)
315+
.only()
316+
.run_with_handle();
317+
let subscriber = collector.with(filter);
318+
319+
with_default(subscriber, || {
320+
tracing::info!("should be enabled");
321+
tracing::warn!("should be enabled");
322+
tracing::info!(target: "hello", "should be disabled");
323+
});
324+
325+
finished.assert_finished();
326+
}
327+
328+
#[test]
329+
fn more_specific_dynamic_filter_more_verbose() {
330+
let filter = EnvFilter::new("info,[{hello=4}]=debug");
331+
let (collector, finished) = collector::mock()
332+
.new_span(expect::span().at_level(Level::INFO))
333+
.drop_span("enabled info")
334+
.new_span(
335+
expect::span()
336+
.at_level(Level::DEBUG)
337+
.with_fields(expect::field("hello").with_value(&4_u64)),
338+
)
339+
.drop_span("enabled debug")
340+
.event(expect::event().with_fields(expect::msg("marker")))
341+
.only()
342+
.run_with_handle();
343+
let subscriber = collector.with(filter);
344+
345+
with_default(subscriber, || {
346+
tracing::info_span!("enabled info");
347+
tracing::debug_span!("disabled debug");
348+
tracing::debug_span!("enabled debug", hello = &4_u64);
349+
350+
// .only() doesn't work when we don't enter/exit spans
351+
tracing::info!("marker");
352+
});
353+
354+
finished.assert_finished();
355+
}
356+
357+
/// This is a negative test. This functionality should work, but doesn't.
358+
///
359+
/// If an improvement to `EnvFilter` fixes this test, then the `#[should_panic]`
360+
/// can be removed and the test kept as it is. If the test requires some sort of
361+
/// modification, then care should be taken.
362+
///
363+
/// Fixing this test would resolve https://github.com/tokio-rs/tracing/issues/1388
364+
/// (and probably a few more issues as well).
365+
#[test]
366+
#[should_panic(
367+
expected = "[more_specific_dynamic_filter_less_verbose] expected a new span \
368+
at level `Level(Warn)`,\n[more_specific_dynamic_filter_less_verbose] but \
369+
got one at level `Level(Info)` instead."
370+
)]
371+
fn more_specific_dynamic_filter_less_verbose() {
372+
let filter = EnvFilter::new("info,[{hello=4}]=warn");
373+
let (collector, finished) = collector::mock()
374+
.new_span(expect::span().at_level(Level::INFO))
375+
.drop_span("enabled info")
376+
.new_span(
377+
expect::span()
378+
.at_level(Level::WARN)
379+
.with_fields(expect::field("hello").with_value(&100_u64)),
380+
)
381+
.drop_span("enabled hello=100 warn")
382+
.new_span(
383+
expect::span()
384+
.at_level(Level::WARN)
385+
.with_fields(expect::field("hello").with_value(&4_u64)),
386+
)
387+
.drop_span("enabled hello=4 warn")
388+
.event(expect::event().with_fields(expect::msg("marker")))
389+
.only()
390+
.run_with_handle();
391+
let subscriber = collector.with(filter);
392+
393+
with_default(subscriber, || {
394+
tracing::info_span!("enabled info");
395+
tracing::warn_span!("enabled hello=100 warn", hello = &100_u64);
396+
tracing::info_span!("disabled hello=4 info", hello = &4_u64);
397+
tracing::warn_span!("enabled hello=4 warn", hello = &4_u64);
398+
399+
// .only() doesn't work when we don't enter/exit spans
400+
tracing::info!("marker");
401+
});
402+
403+
finished.assert_finished();
404+
}

0 commit comments

Comments
 (0)