tracing_assertions/
lib.rs

1//! [![Crates.io](https://img.shields.io/crates/v/tracing-assertions)](https://crates.io/crates/tracing-assertions)
2//! [![docs](https://img.shields.io/crates/v/tracing-assertions?color=yellow&label=docs)](https://docs.rs/tracing-assertions)
3//! [![codecov](https://codecov.io/gh/JonathanWoollett-Light/tracing-assertions/branch/master/graph/badge.svg?token=II1xtnbCDX)](https://codecov.io/gh/JonathanWoollett-Light/tracing-assertions)
4//!
5//! An assertions framework for [tracing](https://docs.rs/tracing/latest/tracing/).
6//!
7//! Simpler and faster than the alternatives.
8//!
9//! ```
10//! use tracing_subscriber::layer::SubscriberExt;
11//! // Initialize a subscriber with the layer.
12//! let asserter = tracing_assertions::Layer::default();
13//! let registry = tracing_subscriber::Registry::default();
14//! let subscriber = registry.with(asserter.clone());
15//! let guard = tracing::subscriber::set_default(subscriber);
16//! let one = asserter.matches("one");
17//! let two = asserter.matches("two");
18//! let and = &one & &two;
19//! tracing::info!("one");
20//! one.assert();
21//! tracing::info!("two");
22//! two.assert();
23//! and.assert();
24//!
25//! drop(guard); // Drop `subscriber` as the current subscriber.
26//! ```
27//!
28//! ### Failing
29//!
30//! When failing e.g.
31//! ```should_panic
32//! # use tracing_subscriber::layer::SubscriberExt;
33//! # let asserter = tracing_assertions::Layer::default();
34//! # let registry = tracing_subscriber::Registry::default();
35//! # let subscriber = registry.with(asserter.clone());
36//! # let guard = tracing::subscriber::set_default(subscriber);
37//! let one = asserter.matches("one");
38//! let two = asserter.matches("two");
39//! let and = &one & &two;
40//! tracing::info!("one");
41//! and.assert();
42//! # drop(guard);
43//! ```
44//! Outputs:
45//! <pre>
46//! thread 'main' panicked at src/lib.rs:14:5:
47//! (<font color="green">"one"</font> && <font color="red">"two"</font>)
48//! </pre>
49//!
50//! ### Operations
51//!
52//! Logical operations clone the underlying assertions.
53//! ```
54//! # use tracing_subscriber::layer::SubscriberExt;
55//! # let asserter = tracing_assertions::Layer::default();
56//! # let registry = tracing_subscriber::Registry::default();
57//! # let subscriber = registry.with(asserter.clone());
58//! # let guard = tracing::subscriber::set_default(subscriber);
59//! let one = asserter.matches("one");
60//! let two = asserter.matches("two");
61//! let and = &one & &two;
62//! tracing::info!("one");
63//! tracing::info!("two");
64//! one.assert().reset();
65//! and.assert().reset();
66//! two.assert();
67//! (!one).assert();
68//! (!and).assert();
69//! ```
70//! Calling [`Assertion::reset`] on `one` does not affect the value of `and` and calling [`Assertion::reset`] on `and` does not affect the value of `two`.
71//!
72//! ### Similar crates
73//! - [test-log](https://crates.io/crates/test-log): A replacement of the `#[test]` attribute that initializes logging and/or tracing infrastructure before running tests.
74//! - [tracing_test](https://crates.io/crates/tracing-test): Helper functions and macros that allow for easier testing of crates that use `tracing`.
75//! - [tracing-fluent-assertions](https://crates.io/crates/tracing-fluent-assertions): An fluent assertions framework for tracing.
76//!
77
78use std::fmt::Debug;
79use std::ops::{BitAnd, BitOr};
80use std::sync::atomic::AtomicBool;
81use std::sync::atomic::Ordering::SeqCst;
82use std::sync::Arc;
83use std::sync::Mutex;
84use tracing::field::Field;
85use tracing::Event;
86use tracing::Subscriber;
87use tracing_subscriber::field::Visit;
88use tracing_subscriber::layer::Context;
89
90#[cfg(feature = "regex")]
91use regex::Regex;
92
93/// The assertion layer.
94#[derive(Default, Clone, Debug)]
95pub struct Layer(Arc<InnerLayer>);
96
97/// The inner layer shared between assertions and the assertion layer.
98///
99/// You should probably not use this directly.
100#[derive(Default, Debug)]
101struct InnerLayer {
102    pass_all: AtomicBool,
103    assertions: Mutex<Vec<Arc<InnerAssertion>>>,
104}
105
106impl Layer {
107    /// Creates a string matching assertion.
108    ///
109    /// # Panics
110    ///
111    /// When the internal mutex is poisoned.
112    pub fn matches(&self, s: impl Into<String>) -> Assertion {
113        let inner_assertion = Arc::new(InnerAssertion {
114            boolean: AtomicBool::new(false),
115            assertion_type: AssertionType::Matches(s.into()),
116        });
117        self.0
118            .assertions
119            .lock()
120            .unwrap()
121            .push(inner_assertion.clone());
122        Assertion(AssertionWrapper::One {
123            assertion: inner_assertion.clone(),
124            asserter: self.0.clone(),
125        })
126    }
127    /// Creates a string matching assertion on the debug string of a value.
128    ///
129    /// This exists because
130    /// ```
131    /// # use tracing_subscriber::{layer::SubscriberExt, Registry};
132    /// # #[derive(Debug)]
133    /// # struct MyStruct { x: i32, y: i32 }
134    /// # let asserter = tracing_assertions::Layer::default();
135    /// # let base_subscriber = Registry::default();
136    /// # let subscriber = base_subscriber.with(asserter.clone());
137    /// # let guard = tracing::subscriber::set_default(subscriber);
138    /// let condition = asserter.debug(MyStruct { x: 2, y: 3 });
139    /// ```
140    /// is more readable than
141    /// ```
142    /// # use tracing_subscriber::{layer::SubscriberExt, Registry};
143    /// # #[derive(Debug)]
144    /// # struct MyStruct { x: i32, y: i32 }
145    /// # let asserter = tracing_assertions::Layer::default();
146    /// # let base_subscriber = Registry::default();
147    /// # let subscriber = base_subscriber.with(asserter.clone());
148    /// # let guard = tracing::subscriber::set_default(subscriber);
149    /// let condition = asserter.matches(format!("{:?}", MyStruct { x: 2, y: 3 }));
150    pub fn debug(&self, s: impl Debug) -> Assertion {
151        self.matches(format!("{s:?}"))
152    }
153    /// Creates a regex matching assertion.
154    ///
155    /// # Errors
156    ///
157    /// When the conversion to [`Regex`] fails.
158    ///
159    /// # Panics
160    ///
161    /// When the internal mutex is poisoned.
162    #[cfg(feature = "regex")]
163    pub fn regex<T>(&self, s: T) -> Result<Assertion, <Regex as TryFrom<T>>::Error>
164    where
165        Regex: TryFrom<T>,
166    {
167        let inner_assertion = Arc::new(InnerAssertion {
168            boolean: AtomicBool::new(false),
169            assertion_type: AssertionType::Regex(Regex::try_from(s)?),
170        });
171        self.0
172            .assertions
173            .lock()
174            .unwrap()
175            .push(inner_assertion.clone());
176        Ok(Assertion(AssertionWrapper::One {
177            assertion: inner_assertion.clone(),
178            asserter: self.0.clone(),
179        }))
180    }
181    /// The inverse of [`Layer::disable`].
182    pub fn enable(&self) {
183        self.0.pass_all.store(false, SeqCst);
184    }
185    /// Tells all assertions to pass.
186    ///
187    /// Useful when you want to disables certain tested logs in a
188    /// test for debugging without needing to comment out all the
189    /// assertions you added.
190    pub fn disable(&self) {
191        self.0.pass_all.store(true, SeqCst);
192    }
193}
194
195#[derive(Debug, Clone)]
196enum AssertionType {
197    Matches(String),
198    #[cfg(feature = "regex")]
199    Regex(Regex),
200}
201
202impl std::fmt::Display for AssertionType {
203    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
204        use AssertionType::*;
205        match self {
206            Matches(matches) => write!(f, "{matches}"),
207            #[cfg(feature = "regex")]
208            Regex(regex) => write!(f, "{regex}"),
209        }
210    }
211}
212
213/// An assertion.
214#[derive(Debug, Clone)]
215pub struct Assertion(AssertionWrapper);
216
217/// This exists since there is no way of making enum variants private.
218#[derive(Debug)]
219enum AssertionWrapper {
220    And {
221        lhs: Box<Assertion>,
222        rhs: Box<Assertion>,
223    },
224    Or {
225        lhs: Box<Assertion>,
226        rhs: Box<Assertion>,
227    },
228    One {
229        assertion: Arc<InnerAssertion>,
230        asserter: Arc<InnerLayer>,
231    },
232    Not {
233        assertion: Box<Assertion>,
234    },
235}
236impl Clone for AssertionWrapper {
237    fn clone(&self) -> AssertionWrapper {
238        use AssertionWrapper::*;
239        match &self {
240            One {
241                assertion,
242                asserter,
243            } => {
244                let new_assertion = Arc::new(InnerAssertion {
245                    boolean: AtomicBool::from(assertion.boolean.load(SeqCst)),
246                    assertion_type: assertion.assertion_type.clone(),
247                });
248                asserter
249                    .assertions
250                    .lock()
251                    .unwrap()
252                    .push(new_assertion.clone());
253                One {
254                    assertion: new_assertion,
255                    asserter: asserter.clone(),
256                }
257            }
258            Not { assertion } => Not {
259                assertion: assertion.clone(),
260            },
261            And { lhs, rhs } => And {
262                lhs: lhs.clone(),
263                rhs: rhs.clone(),
264            },
265            Or { lhs, rhs } => Or {
266                lhs: lhs.clone(),
267                rhs: rhs.clone(),
268            },
269        }
270    }
271}
272
273impl Assertion {
274    /// Evaluates the assertion.
275    ///
276    /// # Panics
277    ///
278    /// When the assertion is false.
279    #[allow(clippy::must_use_candidate)] // `let _ = x.assert();` is ugly.
280    #[track_caller]
281    pub fn assert(&self) -> &Self {
282        assert!(bool::from(self), "{}", self.ansi());
283        self
284    }
285    /// Create a new assertion with the same condition.
286    ///
287    /// ```
288    /// use tracing_subscriber::layer::SubscriberExt;
289    /// let asserter = tracing_assertions::Layer::default();
290    /// let registry = tracing_subscriber::Registry::default();
291    /// let subscriber = registry.with(asserter.clone());
292    /// let guard = tracing::subscriber::set_default(subscriber);
293    /// let one = asserter.matches("one");
294    /// tracing::info!("one");
295    /// one.assert();
296    /// let one2 = one.repeat();
297    /// (!&one2).assert();
298    /// tracing::info!("one");
299    /// one2.assert();
300    /// ```
301    ///
302    /// # Panics
303    ///
304    /// When the inner mutex is poisoned.
305    #[must_use]
306    pub fn repeat(&self) -> Self {
307        use AssertionWrapper::*;
308        let inner = match &self.0 {
309            One {
310                assertion,
311                asserter,
312            } => {
313                let new_assertion = Arc::new(InnerAssertion {
314                    boolean: AtomicBool::new(false),
315                    assertion_type: assertion.assertion_type.clone(),
316                });
317                asserter
318                    .assertions
319                    .lock()
320                    .unwrap()
321                    .push(new_assertion.clone());
322                One {
323                    assertion: new_assertion,
324                    asserter: asserter.clone(),
325                }
326            }
327            Not { assertion } => Not {
328                assertion: Box::new(assertion.repeat()),
329            },
330            And { lhs, rhs } => And {
331                lhs: Box::new(lhs.repeat()),
332                rhs: Box::new(rhs.repeat()),
333            },
334            Or { lhs, rhs } => Or {
335                lhs: Box::new(lhs.repeat()),
336                rhs: Box::new(rhs.repeat()),
337            },
338        };
339        Self(inner)
340    }
341
342    /// Resets the assertion.
343    ///
344    /// ```
345    /// use tracing_subscriber::layer::SubscriberExt;
346    /// let asserter = tracing_assertions::Layer::default();
347    /// let registry = tracing_subscriber::Registry::default();
348    /// let subscriber = registry.with(asserter.clone());
349    /// let guard = tracing::subscriber::set_default(subscriber);
350    /// let one = asserter.matches("one");
351    /// tracing::info!("one");
352    /// one.assert().reset();
353    /// (!&one).assert();
354    /// tracing::info!("one");
355    /// one.assert();
356    /// ```
357    ///
358    /// # Panics
359    ///
360    /// When the inner mutex is poisoned.
361    pub fn reset(&self) {
362        use AssertionWrapper::*;
363        match &self.0 {
364            One {
365                assertion,
366                asserter,
367            } => {
368                if assertion.boolean.swap(false, SeqCst) {
369                    asserter.assertions.lock().unwrap().push(assertion.clone());
370                }
371            }
372            Not { assertion } => assertion.reset(),
373            And { lhs, rhs } | Or { lhs, rhs } => {
374                lhs.reset();
375                rhs.reset();
376            }
377        }
378    }
379
380    fn ansi(&self) -> String {
381        use AssertionWrapper::*;
382
383        match &self.0 {
384            One {
385                assertion,
386                asserter,
387            } => {
388                let is_true = if asserter.pass_all.load(SeqCst) {
389                    true
390                } else {
391                    assertion.boolean.load(std::sync::atomic::Ordering::SeqCst)
392                };
393                let str = format!("{:?}", assertion.assertion_type.to_string());
394                let out = if is_true {
395                    ansi_term::Colour::Green.paint(str)
396                } else {
397                    ansi_term::Colour::Red.paint(str)
398                };
399                out.to_string()
400            }
401            And { lhs, rhs } => format!("({} && {})", lhs.ansi(), rhs.ansi()),
402            Or { lhs, rhs } => format!("({} || {})", lhs.ansi(), rhs.ansi()),
403            Not { assertion } => format!("!{}", assertion.ansi()),
404        }
405    }
406}
407
408impl std::ops::Not for Assertion {
409    type Output = Self;
410    fn not(self) -> Self::Output {
411        !&self
412    }
413}
414impl std::ops::Not for &Assertion {
415    type Output = Assertion;
416    fn not(self) -> Self::Output {
417        Assertion(AssertionWrapper::Not {
418            assertion: Box::new(self.clone()),
419        })
420    }
421}
422
423impl BitAnd for Assertion {
424    type Output = Self;
425    fn bitand(self, rhs: Self) -> Self::Output {
426        Assertion(AssertionWrapper::And {
427            lhs: Box::new(self.clone()),
428            rhs: Box::new(rhs.clone()),
429        })
430    }
431}
432impl BitAnd for &Assertion {
433    type Output = Assertion;
434    fn bitand(self, rhs: Self) -> Self::Output {
435        Assertion(AssertionWrapper::And {
436            lhs: Box::new(self.clone()),
437            rhs: Box::new(rhs.clone()),
438        })
439    }
440}
441impl BitAnd<&Assertion> for Assertion {
442    type Output = Assertion;
443    fn bitand(self, rhs: &Self) -> Self::Output {
444        Assertion(AssertionWrapper::And {
445            lhs: Box::new(self.clone()),
446            rhs: Box::new(rhs.clone()),
447        })
448    }
449}
450impl BitAnd<Assertion> for &Assertion {
451    type Output = Assertion;
452    fn bitand(self, rhs: Assertion) -> Self::Output {
453        Assertion(AssertionWrapper::And {
454            lhs: Box::new(self.clone()),
455            rhs: Box::new(rhs.clone()),
456        })
457    }
458}
459impl BitOr for Assertion {
460    type Output = Self;
461    fn bitor(self, rhs: Self) -> Self::Output {
462        Assertion(AssertionWrapper::Or {
463            lhs: Box::new(self.clone()),
464            rhs: Box::new(rhs.clone()),
465        })
466    }
467}
468impl BitOr for &Assertion {
469    type Output = Assertion;
470    fn bitor(self, rhs: Self) -> Self::Output {
471        Assertion(AssertionWrapper::Or {
472            lhs: Box::new(self.clone()),
473            rhs: Box::new(rhs.clone()),
474        })
475    }
476}
477impl BitOr<&Assertion> for Assertion {
478    type Output = Self;
479    fn bitor(self, rhs: &Assertion) -> Self::Output {
480        Assertion(AssertionWrapper::Or {
481            lhs: Box::new(self.clone()),
482            rhs: Box::new(rhs.clone()),
483        })
484    }
485}
486impl BitOr<Assertion> for &Assertion {
487    type Output = Assertion;
488    fn bitor(self, rhs: Assertion) -> Self::Output {
489        Assertion(AssertionWrapper::Or {
490            lhs: Box::new(self.clone()),
491            rhs: Box::new(rhs.clone()),
492        })
493    }
494}
495
496impl From<&Assertion> for bool {
497    fn from(value: &Assertion) -> Self {
498        use AssertionWrapper::*;
499        match &value.0 {
500            One {
501                assertion,
502                asserter,
503            } => {
504                if asserter.pass_all.load(SeqCst) {
505                    return true;
506                }
507                assertion.boolean.load(std::sync::atomic::Ordering::SeqCst)
508            }
509            And { lhs, rhs } => bool::from(&**lhs) && bool::from(&**rhs),
510            Or { lhs, rhs } => bool::from(&**lhs) || bool::from(&**rhs),
511            Not { assertion } => !bool::from(&**assertion),
512        }
513    }
514}
515impl From<Assertion> for bool {
516    fn from(value: Assertion) -> Self {
517        bool::from(&value)
518    }
519}
520
521/// The inner assertion shared between assertions and the assertion layer.
522///
523/// You should probably not use this directly.
524#[derive(Debug)]
525struct InnerAssertion {
526    boolean: AtomicBool,
527    assertion_type: AssertionType,
528}
529
530struct EventVisitor<'a>(&'a mut String);
531impl Visit for EventVisitor<'_> {
532    fn record_debug(&mut self, _field: &Field, value: &dyn std::fmt::Debug) {
533        *self.0 = format!("{value:?}");
534    }
535}
536
537impl<S: Subscriber> tracing_subscriber::layer::Layer<S> for Layer {
538    fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
539        // TODO This is a stupid way to access the message, surely there is a better way to get the message.
540        let mut message = String::new();
541        event.record(&mut EventVisitor(&mut message) as &mut dyn Visit);
542        let mut assertions = self.0.assertions.lock().unwrap();
543        let mut i = 0;
544        while i < assertions.len() {
545            let result = match &assertions[i].assertion_type {
546                AssertionType::Matches(expected) => *expected == message,
547                AssertionType::Regex(regex) => regex.is_match(&message),
548            };
549            assertions[i].boolean.store(result, SeqCst);
550            if result {
551                assertions.remove(i);
552            } else {
553                i += 1;
554            }
555        }
556    }
557}
558
559#[cfg(test)]
560mod tests {
561    use tracing::info;
562
563    use super::*;
564    use tracing_subscriber::{layer::SubscriberExt, Registry};
565
566    #[cfg(feature = "regex")]
567    #[test]
568    fn regex_pass() {
569        let asserter = Layer::default();
570        let base_subscriber = Registry::default();
571        let subscriber = base_subscriber.with(asserter.clone());
572        let guard = tracing::subscriber::set_default(subscriber);
573        let condition = asserter.regex("01234.6789").unwrap();
574        info!("0123456789");
575        condition.assert();
576        drop(guard);
577    }
578
579    #[cfg(feature = "regex")]
580    #[should_panic(expected = "\u{1b}[31m\"01234.789\"\u{1b}[0m")]
581    #[test]
582    fn regex_fail() {
583        let asserter = Layer::default();
584        let base_subscriber = Registry::default();
585        let subscriber = base_subscriber.with(asserter.clone());
586        let guard = tracing::subscriber::set_default(subscriber);
587        let condition = asserter.regex("01234.789").unwrap();
588        info!("0123456789");
589        condition.assert();
590        drop(guard);
591    }
592
593    #[test]
594    fn debug() {
595        #[allow(dead_code)]
596        #[derive(Debug)]
597        struct MyStruct {
598            x: i32,
599            y: i32,
600        }
601        let asserter = Layer::default();
602        let base_subscriber = Registry::default();
603        let subscriber = base_subscriber.with(asserter.clone());
604        let guard = tracing::subscriber::set_default(subscriber);
605        let value = MyStruct { x: 2, y: 3 };
606        let condition = asserter.debug(&value);
607        info!("{value:?}");
608        condition.assert();
609        drop(guard);
610    }
611
612    #[test]
613    fn pass_all() {
614        let asserter = Layer::default();
615        let base_subscriber = Registry::default();
616        let subscriber = base_subscriber.with(asserter.clone());
617        let guard = tracing::subscriber::set_default(subscriber);
618
619        info!("stuff");
620        let condition = asserter.matches("missing");
621        asserter.disable();
622        info!("more stuff");
623        condition.assert();
624        asserter.enable();
625        (!condition).assert();
626
627        drop(guard);
628    }
629
630    #[test]
631    #[should_panic(
632        expected = "((\u{1b}[32m\"one\"\u{1b}[0m && \u{1b}[31m\"two\"\u{1b}[0m) || (\u{1b}[31m\"three\"\u{1b}[0m && !\u{1b}[31m\"four\"\u{1b}[0m))"
633    )]
634    fn panics() {
635        let asserter = Layer::default();
636        let registry = Registry::default();
637        let subscriber = registry.with(asserter.clone());
638        let guard = tracing::subscriber::set_default(subscriber);
639        let one = asserter.matches("one");
640        let two = asserter.matches("two");
641        let three = asserter.matches("three");
642        let four = asserter.matches("four");
643        let assertion = one & two | three & !four;
644        info!("one");
645        asserter.disable();
646        assertion.assert();
647        assert_eq!(assertion.ansi(),"((\u{1b}[32m\"one\"\u{1b}[0m && \u{1b}[32m\"two\"\u{1b}[0m) || (\u{1b}[32m\"three\"\u{1b}[0m && !\u{1b}[32m\"four\"\u{1b}[0m))");
648        asserter.enable();
649        assertion.assert();
650        drop(guard);
651    }
652
653    #[test]
654    fn and() {
655        let asserter = Layer::default();
656        let registry = Registry::default();
657        let subscriber = registry.with(asserter.clone());
658        let guard = tracing::subscriber::set_default(subscriber);
659        let one = asserter.matches("one");
660        let two = asserter.matches("two");
661        let a = &one & two.clone();
662        let b = one.clone() & &two;
663        let c = &one & &two;
664        let d = one & two;
665        info!("one");
666        info!("two");
667        a.assert();
668        b.assert();
669        c.assert();
670        d.assert();
671        drop(guard);
672    }
673
674    #[test]
675    fn or() {
676        let asserter = Layer::default();
677        let registry = Registry::default();
678        let subscriber = registry.with(asserter.clone());
679        let guard = tracing::subscriber::set_default(subscriber);
680        let one = asserter.matches("one");
681        let two = asserter.matches("two");
682        let a = &one | two.clone();
683        let b = one.clone() | &two;
684        let c = &one | &two;
685        let d = one | two;
686        info!("one");
687        a.assert();
688        b.assert();
689        c.assert();
690        d.assert();
691        drop(guard);
692    }
693
694    #[test]
695    fn matches() {
696        let asserter = Layer::default();
697        let base_subscriber = Registry::default();
698        let subscriber = base_subscriber.with(asserter.clone());
699        let guard = tracing::subscriber::set_default(subscriber);
700
701        let two = asserter.matches("two");
702        let three = asserter.matches("three");
703        let or = &two | &three;
704        let and = &two & &three;
705        let or2 = two.clone() | three.clone();
706        let and2 = two.clone() & three.clone();
707
708        // The assertion is false as message matching `two` has not been encountered.
709        (!&two).assert();
710
711        info!("one");
712
713        // Still false.
714        (!&two).assert();
715        (!&or).assert();
716        (!&or2).assert();
717
718        info!("two");
719
720        // The assertion is true as a message matching `two` has been encountered.
721        two.assert();
722        or.assert();
723        or2.assert();
724        (!&and).assert();
725        (!&and2).assert();
726
727        info!("three");
728
729        // Still true.
730        two.assert();
731        and.assert();
732        and2.assert();
733
734        // If an assertion is created after the message, it will be false.
735        // Each assertion can only be fulfilled based on messages after its creation.
736        let two = asserter.matches("two");
737        (!&two).assert();
738        assert!(!bool::from(two));
739
740        drop(guard);
741    }
742
743    #[test]
744    fn repeat() {
745        let asserter = Layer::default();
746        let base_subscriber = Registry::default();
747        let subscriber = base_subscriber.with(asserter.clone());
748        let guard = tracing::subscriber::set_default(subscriber);
749
750        let one = asserter.matches("one");
751        let two = asserter.matches("two");
752        let or = &one | &two;
753        let and = &one & &two;
754        let not = !&one;
755
756        info!("one");
757        info!("two");
758
759        one.assert();
760        two.assert();
761        or.assert();
762        and.assert();
763        (!&not).assert();
764
765        let one2 = one.repeat();
766        let two2 = two.repeat();
767        let or2 = or.repeat();
768        let and2 = and.repeat();
769        let not2 = not.repeat();
770
771        (!&one2).assert();
772        (!&two2).assert();
773        (!&or2).assert();
774        (!&and2).assert();
775        (!(!&not2)).assert();
776
777        info!("one");
778        info!("two");
779
780        one2.assert();
781        two2.assert();
782        or2.assert();
783        and2.assert();
784        (!&not2).assert();
785
786        drop(guard);
787    }
788
789    #[test]
790    fn reset() {
791        let asserter = Layer::default();
792        let base_subscriber = Registry::default();
793        let subscriber = base_subscriber.with(asserter.clone());
794        let guard = tracing::subscriber::set_default(subscriber);
795
796        let one = asserter.matches("one");
797        let two = asserter.matches("two");
798        let or = &one | &two;
799        let and = &one & &two;
800        let not = !&one;
801
802        not.assert().reset();
803
804        info!("one");
805        info!("two");
806
807        one.assert().reset();
808        two.assert().reset();
809        or.assert().reset();
810        and.assert().reset();
811
812        (!&one).assert();
813        (!&two).assert();
814        (!&or).assert();
815        (!&and).assert();
816        (!&not).assert();
817
818        info!("one");
819        info!("two");
820
821        one.assert();
822        two.assert();
823        or.assert();
824        and.assert();
825        (!&not).assert();
826
827        drop(guard);
828    }
829}