tracing_mock/
layer.rs

1//! An implementation of the [`Layer`] trait which validates that
2//! the `tracing` data it receives matches the expected output for a test.
3//!
4//!
5//! The [`MockLayer`] is the central component in these tools. The
6//! `MockLayer` has expectations set on it which are later
7//! validated as the code under test is run.
8//!
9//! ```
10//! use tracing_mock::{expect, layer};
11//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
12//!
13//! let (layer, handle) = layer::mock()
14//!     // Expect a single event with a specified message
15//!     .event(expect::event().with_fields(expect::msg("droids")))
16//!     .run_with_handle();
17//!
18//! // Use `set_default` to apply the `MockSubscriber` until the end
19//! // of the current scope (when the guard `_subscriber` is dropped).
20//! let _subscriber =  tracing_subscriber::registry()
21//!     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
22//!     .set_default();
23//!
24//! // These *are* the droids we are looking for
25//! tracing::info!("droids");
26//!
27//! // Use the handle to check the assertions. This line will panic if an
28//! // assertion is not met.
29//! handle.assert_finished();
30//! ```
31//!
32//! A more complex example may consider multiple spans and events with
33//! their respective fields:
34//!
35//! ```
36//! use tracing_mock::{expect, layer};
37//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
38//!
39//! let span = expect::span()
40//!     .named("my_span");
41//! let (layer, handle) = layer::mock()
42//!     // Enter a matching span
43//!     .enter(&span)
44//!     // Record an event with message "collect parting message"
45//!     .event(expect::event().with_fields(expect::msg("say hello")))
46//!     // Exit a matching span
47//!     .exit(&span)
48//!     // Expect no further messages to be recorded
49//!     .only()
50//!     // Return the layer and handle
51//!     .run_with_handle();
52//!
53//! // Use `set_default` to apply the `MockLayers` until the end
54//! // of the current scope (when the guard `_subscriber` is dropped).
55//! let _subscriber = tracing_subscriber::registry()
56//!     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
57//!     .set_default();
58//!
59//! {
60//!     let span = tracing::trace_span!(
61//!         "my_span",
62//!         greeting = "hello world",
63//!     );
64//!
65//!     let _guard = span.enter();
66//!     tracing::info!("say hello");
67//! }
68//!
69//! // Use the handle to check the assertions. This line will panic if an
70//! // assertion is not met.
71//! handle.assert_finished();
72//! ```
73//!
74//! If we modify the previous example so that we **don't** enter the
75//! span before recording an event, the test will fail:
76//!
77//! ```should_panic
78//! use tracing_mock::{expect, layer};
79//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};  
80//!
81//! let span = expect::span()
82//!     .named("my_span");
83//! let (layer, handle) = layer::mock()
84//!     // Enter a matching span
85//!     .enter(&span)
86//!     // Record an event with message "collect parting message"
87//!     .event(expect::event().with_fields(expect::msg("say hello")))
88//!     // Exit a matching span
89//!     .exit(&span)
90//!     // Expect no further messages to be recorded
91//!     .only()
92//!     // Return the subscriber and handle
93//!     .run_with_handle();
94//!
95//! // Use `set_default` to apply the `MockSubscriber` until the end
96//! // of the current scope (when the guard `_subscriber` is dropped).
97//! let _subscriber =  tracing_subscriber::registry()
98//!     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
99//!     .set_default();
100//!
101//! {
102//!     let span = tracing::trace_span!(
103//!         "my_span",
104//!         greeting = "hello world",
105//!     );
106//!
107//!     // Don't enter the span.
108//!     // let _guard = span.enter();
109//!     tracing::info!("say hello");
110//! }
111//!
112//! // Use the handle to check the assertions. This line will panic if an
113//! // assertion is not met.
114//! handle.assert_finished();
115//! ```
116//!
117//! [`Layer`]: trait@tracing_subscriber::layer::Layer
118use std::{
119    collections::VecDeque,
120    fmt,
121    sync::{Arc, Mutex},
122};
123
124use tracing_core::{
125    span::{Attributes, Id, Record},
126    Event, Subscriber,
127};
128use tracing_subscriber::{
129    layer::{Context, Layer},
130    registry::{LookupSpan, SpanRef},
131};
132
133use crate::{
134    ancestry::{get_ancestry, ActualAncestry, HasAncestry},
135    event::ExpectedEvent,
136    expect::Expect,
137    span::{ActualSpan, ExpectedSpan, NewSpan},
138    subscriber::MockHandle,
139};
140
141/// Create a [`MockLayerBuilder`] used to construct a
142/// [`MockLayer`].
143///
144/// For additional information and examples, see the [`layer`]
145/// module and [`MockLayerBuilder`] documentation.
146///
147/// # Examples
148///
149/// ```
150/// use tracing_mock::{expect, layer};
151/// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
152///
153/// let span = expect::span()
154///     .named("my_span");
155/// let (layer, handle) = layer::mock()
156///     // Enter a matching span
157///     .enter(&span)
158///     // Record an event with message "collect parting message"
159///     .event(expect::event().with_fields(expect::msg("say hello")))
160///     // Exit a matching span
161///     .exit(&span)
162///     // Expect no further messages to be recorded
163///     .only()
164///     // Return the subscriber and handle
165///     .run_with_handle();
166///
167/// // Use `set_default` to apply the `MockSubscriber` until the end
168/// // of the current scope (when the guard `_subscriber` is dropped).
169/// let _subscriber =  tracing_subscriber::registry()
170///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
171///     .set_default();
172///
173/// {
174///     let span = tracing::trace_span!(
175///         "my_span",
176///         greeting = "hello world",
177///     );
178///
179///     let _guard = span.enter();
180///     tracing::info!("say hello");
181/// }
182///
183/// // Use the handle to check the assertions. This line will panic if an
184/// // assertion is not met.
185/// handle.assert_finished();
186/// ```
187///
188/// [`layer`]: mod@crate::layer
189#[must_use]
190pub fn mock() -> MockLayerBuilder {
191    MockLayerBuilder {
192        expected: Default::default(),
193        name: std::thread::current()
194            .name()
195            .map(String::from)
196            .unwrap_or_default(),
197    }
198}
199
200/// Create a [`MockLayerBuilder`] with a name already set.
201///
202/// This constructor is equivalent to calling
203/// [`MockLayerBuilder::named`] in the following way"
204/// `layer::mock().named(name)`.
205///
206/// For additional information and examples, see the [`layer`]
207/// module and [`MockLayerBuilder`] documentation.
208///
209/// # Examples
210///
211/// The example from [`MockLayerBuilder::named`] could be rewritten as:
212///
213/// ```should_panic
214/// use tracing_mock::{expect, layer};
215/// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
216///
217/// let (layer_1, handle_1) = layer::named("subscriber-1")
218///     .event(expect::event())
219///     .run_with_handle();
220///
221/// let (layer_2, handle_2) = layer::named("subscriber-2")
222///     .event(expect::event())
223///     .run_with_handle();
224///
225/// let _subscriber =  tracing_subscriber::registry()
226///     .with(
227///         layer_2.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true))
228///     )
229///     .set_default();
230/// {
231///     let _subscriber =  tracing_subscriber::registry()
232///         .with(
233///             layer_1
234///                 .with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true))
235///         )
236///         .set_default();
237///
238///     tracing::info!("a");
239/// }
240///
241/// handle_1.assert_finished();
242/// handle_2.assert_finished();
243/// ```
244///
245/// [`MockLayerBuilder::named`]: fn@crate::layer::MockLayerBuilder::named
246/// [`layer`]: mod@crate::layer
247#[must_use]
248pub fn named(name: impl std::fmt::Display) -> MockLayerBuilder {
249    mock().named(name)
250}
251
252/// A builder for constructing [`MockLayer`]s.
253///
254/// The methods on this builder set expectations which are then
255/// validated by the constructed [`MockLayer`].
256///
257/// For a detailed description and examples see the documentation
258/// for the methods and the [`layer`] module.
259///
260/// [`layer`]: mod@crate::layer
261
262#[derive(Debug)]
263pub struct MockLayerBuilder {
264    expected: VecDeque<Expect>,
265    name: String,
266}
267
268/// A layer which validates the traces it receives.
269///
270/// A `MockLayer` is constructed with a
271/// [`MockLayerBuilder`]. For a detailed description and examples,
272/// see the documentation for that struct and for the [`layer`]
273/// module.
274///
275/// [`layer`]: mod@crate::layer
276pub struct MockLayer {
277    expected: Arc<Mutex<VecDeque<Expect>>>,
278    current: Mutex<Vec<Id>>,
279    name: String,
280}
281
282impl MockLayerBuilder {
283    /// Overrides the name printed by the mock layer's debugging output.
284    ///
285    /// The debugging output is displayed if the test panics, or if the test is
286    /// run with `--nocapture`.
287    ///
288    /// By default, the mock layer's name is the  name of the test
289    /// (*technically*, the name of the thread where it was created, which is
290    /// the name of the test unless tests are run with `--test-threads=1`).
291    /// When a test has only one mock layer, this is sufficient. However,
292    /// some tests may include multiple layers, in order to test
293    /// interactions between multiple layers. In that case, it can be
294    /// helpful to give each layers a separate name to distinguish where the
295    /// debugging output comes from.
296    ///
297    /// # Examples
298    ///
299    /// In the following example, we create two layers, both
300    /// expecting to receive an event. As we only record a single
301    /// event, the test will fail:
302    ///
303    /// ```should_panic
304    /// use tracing_mock::{layer, expect};
305    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
306    ///
307    /// let (layer_1, handle_1) = layer::mock()
308    ///     .named("layer-1")
309    ///     .event(expect::event())
310    ///     .run_with_handle();
311    ///
312    /// let (layer_2, handle_2) = layer::mock()
313    ///     .named("layer-2")
314    ///     .event(expect::event())
315    ///     .run_with_handle();
316    ///
317    /// let _subscriber =  tracing_subscriber::registry()
318    ///     .with(
319    ///         layer_2.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true))
320    ///     )
321    ///     .set_default();
322    /// {
323    ///     let _subscriber =  tracing_subscriber::registry()
324    ///         .with(
325    ///             layer_1
326    ///                 .with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true))
327    ///         )
328    ///         .set_default();
329    ///
330    ///     tracing::info!("a");
331    /// }
332    ///
333    /// handle_1.assert_finished();
334    /// handle_2.assert_finished();
335    /// ```
336    ///
337    /// In the test output, we see that the layer which didn't
338    /// received the event was the one named `layer-2`, which is
339    /// correct as the layer named `layer-1` was the default
340    /// when the event was recorded:
341    ///
342    /// ```text
343    /// [main::layer-2] more notifications expected: [
344    ///     Event(
345    ///         MockEvent,
346    ///     ),
347    /// ]', tracing-mock/src/subscriber.rs:472:13
348    /// ```
349    pub fn named(mut self, name: impl fmt::Display) -> Self {
350        use std::fmt::Write;
351        if !self.name.is_empty() {
352            write!(&mut self.name, "::{}", name).unwrap();
353        } else {
354            self.name = name.to_string();
355        }
356        self
357    }
358
359    /// Adds an expectation that an event matching the [`ExpectedEvent`]
360    /// will be recorded next.
361    ///
362    /// The `event` can be a default mock which will match any event
363    /// (`expect::event()`) or can include additional expectations.
364    /// See the [`ExpectedEvent`] documentation for more details.
365    ///
366    /// If an event is recorded that doesn't match the `ExpectedEvent`,
367    /// or if something else (such as entering a span) is recorded
368    /// first, then the expectation will fail.
369    ///
370    /// # Examples
371    ///
372    /// ```
373    /// use tracing_mock::{expect, layer};
374    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
375    ///
376    /// let (layer, handle) = layer::mock()
377    ///     .event(expect::event())
378    ///     .run_with_handle();
379    ///
380    /// let _subscriber = tracing_subscriber::registry()
381    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
382    ///     .set_default();
383    ///
384    /// tracing::info!("event");
385    ///
386    /// handle.assert_finished();
387    /// ```
388    ///
389    /// A span is entered before the event, causing the test to fail:
390    ///
391    /// ```should_panic
392    /// use tracing_mock::{expect, layer};
393    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
394    ///
395    /// let (layer, handle) = layer::mock()
396    ///     .event(expect::event())
397    ///     .run_with_handle();
398    ///
399    /// let _subscriber =  tracing_subscriber::registry()
400    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
401    ///     .set_default();
402    ///
403    /// let span = tracing::info_span!("span");
404    /// let _guard = span.enter();
405    /// tracing::info!("event");
406    ///
407    /// handle.assert_finished();
408    /// ```
409    pub fn event(mut self, event: ExpectedEvent) -> Self {
410        self.expected.push_back(Expect::Event(event));
411        self
412    }
413
414    /// Adds an expectation that the creation of a span will be
415    /// recorded next.
416    ///
417    /// This function accepts `Into<NewSpan>` instead of
418    /// [`ExpectedSpan`] directly. [`NewSpan`] can be used to test
419    /// span fields and the span ancestry.
420    ///
421    /// The new span doesn't need to be entered for this expectation
422    /// to succeed.
423    ///
424    /// If a span is recorded that doesn't match the `ExpectedSpan`,
425    /// or if something else (such as an event) is recorded first,
426    /// then the expectation will fail.
427    ///
428    /// # Examples
429    ///
430    /// ```
431    /// use tracing_mock::{expect, layer};
432    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
433    ///
434    /// let span = expect::span()
435    ///     .at_level(tracing::Level::INFO)
436    ///     .named("the span we're testing")
437    ///     .with_fields(expect::field("testing").with_value(&"yes"));
438    /// let (layer, handle) = layer::mock()
439    ///     .new_span(span)
440    ///     .run_with_handle();
441    ///
442    /// let _subscriber =  tracing_subscriber::registry()
443    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
444    ///     .set_default();
445    ///
446    /// _ = tracing::info_span!("the span we're testing", testing = "yes");
447    ///
448    /// handle.assert_finished();
449    /// ```
450    ///
451    /// An event is recorded before the span is created, causing the
452    /// test to fail:
453    ///
454    /// ```should_panic
455    /// use tracing_mock::{expect, layer};
456    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
457    ///
458    /// let span = expect::span()
459    ///     .at_level(tracing::Level::INFO)
460    ///     .named("the span we're testing")
461    ///     .with_fields(expect::field("testing").with_value(&"yes"));
462    /// let (layer, handle) = layer::mock()
463    ///     .new_span(span)
464    ///     .run_with_handle();
465    ///
466    /// let _subscriber =  tracing_subscriber::registry()
467    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
468    ///     .set_default();
469    ///
470    /// tracing::info!("an event");
471    /// _ = tracing::info_span!("the span we're testing", testing = "yes");
472    ///
473    /// handle.assert_finished();
474    /// ```
475    ///
476    /// [`ExpectedSpan`]: struct@crate::span::ExpectedSpan
477    /// [`NewSpan`]: struct@crate::span::NewSpan
478    pub fn new_span<I>(mut self, new_span: I) -> Self
479    where
480        I: Into<NewSpan>,
481    {
482        self.expected.push_back(Expect::NewSpan(new_span.into()));
483        self
484    }
485
486    /// Adds an expectation that entering a span matching the
487    /// [`ExpectedSpan`] will be recorded next.
488    ///
489    /// This expectation is generally accompanied by a call to
490    /// [`exit`], since an entered span will typically be exited. If used
491    /// together with [`only`], this is likely necessary, because the span
492    /// will be dropped before the test completes (except in rare cases,
493    /// such as if [`std::mem::forget`] is used).
494    ///
495    /// If the span that is entered doesn't match the [`ExpectedSpan`],
496    /// or if something else (such as an event) is recorded first,
497    /// then the expectation will fail.
498    ///
499    /// # Examples
500    ///
501    /// ```
502    /// use tracing_mock::{expect, layer};
503    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
504    ///
505    /// let span = expect::span()
506    ///     .at_level(tracing::Level::INFO)
507    ///     .named("the span we're testing");
508    /// let (layer, handle) = layer::mock()
509    ///     .enter(&span)
510    ///     .exit(&span)
511    ///     .only()
512    ///     .run_with_handle();
513    ///
514    /// let _subscriber =  tracing_subscriber::registry()
515    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
516    ///     .set_default();
517    ///
518    /// {
519    ///     let span = tracing::info_span!("the span we're testing");
520    ///     let _entered = span.enter();
521    /// }
522    ///
523    /// handle.assert_finished();
524    /// ```
525    ///
526    /// An event is recorded before the span is entered, causing the
527    /// test to fail:
528    ///
529    /// ```should_panic
530    /// use tracing_mock::{expect, layer};
531    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
532    ///
533    /// let span = expect::span()
534    ///     .at_level(tracing::Level::INFO)
535    ///     .named("the span we're testing");
536    /// let (layer, handle) = layer::mock()
537    ///     .enter(&span)
538    ///     .exit(&span)
539    ///     .only()
540    ///     .run_with_handle();
541    ///
542    /// let _subscriber =  tracing_subscriber::registry()
543    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
544    ///     .set_default();
545    ///
546    /// {
547    ///     tracing::info!("an event");
548    ///     let span = tracing::info_span!("the span we're testing");
549    ///     let _entered = span.enter();
550    /// }
551    ///
552    /// handle.assert_finished();
553    /// ```
554    ///
555    /// [`exit`]: fn@Self::exit
556    /// [`only`]: fn@Self::only
557    pub fn enter<S>(mut self, span: S) -> Self
558    where
559        S: Into<ExpectedSpan>,
560    {
561        self.expected.push_back(Expect::Enter(span.into()));
562        self
563    }
564
565    /// Adds an expectation that exiting a span matching the
566    /// [`ExpectedSpan`] will be recorded next.
567    ///
568    /// As a span may be entered and exited multiple times,
569    /// this is different from the span being closed. In
570    /// general [`enter`] and `exit` should be paired.
571    ///
572    /// If the span that is exited doesn't match the [`ExpectedSpan`],
573    /// or if something else (such as an event) is recorded first,
574    /// then the expectation will fail.
575    ///
576    /// **Note**: Ensure that the guard returned by [`Span::enter`]
577    /// is dropped before calling [`MockHandle::assert_finished`].
578    ///
579    /// # Examples
580    ///
581    /// ```
582    /// use tracing_mock::{expect, layer};
583    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
584    ///
585    /// let span = expect::span()
586    ///     .at_level(tracing::Level::INFO)
587    ///     .named("the span we're testing");
588    /// let (layer, handle) = layer::mock()
589    ///     .enter(&span)
590    ///     .exit(&span)
591    ///     .only()
592    ///     .run_with_handle();
593    ///
594    /// let _subscriber =  tracing_subscriber::registry()
595    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
596    ///     .set_default();
597    /// {
598    ///     let span = tracing::info_span!("the span we're testing");
599    ///     let _entered = span.enter();
600    /// }
601    ///
602    /// handle.assert_finished();
603    /// ```
604    ///
605    /// An event is recorded before the span is exited, causing the
606    /// test to fail:
607    ///
608    /// ```should_panic
609    /// use tracing_mock::{expect, layer};
610    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
611    ///
612    /// let span = expect::span()
613    ///     .at_level(tracing::Level::INFO)
614    ///     .named("the span we're testing");
615    /// let (layer, handle) = layer::mock()
616    ///     .enter(&span)
617    ///     .exit(&span)
618    ///     .only()
619    ///     .run_with_handle();
620    ///
621    /// let _subscriber =  tracing_subscriber::registry()
622    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
623    ///     .set_default();
624    ///
625    /// {
626    ///     let span = tracing::info_span!("the span we're testing");
627    ///     let _entered = span.enter();
628    ///     tracing::info!("an event");
629    /// }
630    ///
631    /// handle.assert_finished();
632    /// ```
633    ///
634    /// [`enter`]: fn@Self::enter
635    /// [`MockHandle::assert_finished`]: fn@crate::subscriber::MockHandle::assert_finished
636    /// [`Span::enter`]: fn@tracing::Span::enter
637    pub fn exit<S>(mut self, span: S) -> Self
638    where
639        S: Into<ExpectedSpan>,
640    {
641        self.expected.push_back(Expect::Exit(span.into()));
642        self
643    }
644
645    /// Adds an expectation that [`Layer::on_register_dispatch`] will
646    /// be called next.
647    ///
648    /// **Note**: This expectation is usually fulfilled automatically when
649    /// a layer (wrapped in a subscriber) is set as the default via
650    /// [`tracing::subscriber::with_default`] or
651    /// [`tracing::subscriber::set_global_default`], so explicitly expecting
652    /// this is not usually necessary. However, it may be useful when testing
653    /// custom layer implementations that manually call `on_register_dispatch`.
654    ///
655    /// # Examples
656    ///
657    /// ```
658    /// use tracing_mock::{expect, layer};
659    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
660    ///
661    /// let (layer, handle) = layer::mock()
662    ///     .on_register_dispatch()
663    ///     .run_with_handle();
664    ///
665    /// let _subscriber = tracing_subscriber::registry()
666    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
667    ///     .set_default();
668    ///
669    /// // The layer's on_register_dispatch was called when the subscriber was set as default
670    ///
671    /// handle.assert_finished();
672    /// ```
673    ///
674    /// If the `on_register_dispatch` call doesn't make it to the `MockLayer`,
675    /// in case it's wrapped in another Layer that doesn't forward the call,
676    /// then the expectation will fail.
677    ///
678    /// ```should_panic
679    /// # use std::marker::PhantomData;
680    ///
681    /// # use tracing::{Event, Subscriber};
682    /// # use tracing_mock::layer;
683    /// # use tracing_subscriber::{
684    /// #     layer::{Context, SubscriberExt},
685    /// #     util::SubscriberInitExt,
686    /// #     Layer,
687    /// # };
688    ///
689    /// struct WrapLayer<S: Subscriber, L: Layer<S>> {
690    ///     inner: L,
691    ///     _pd: PhantomData<S>,
692    /// }
693    ///
694    /// impl<S: Subscriber, L: Layer<S>> Layer<S> for WrapLayer<S, L> {
695    ///     fn on_register_dispatch(&self, subscriber: &tracing::Dispatch) {
696    ///         // Doesn't forward to `self.inner`
697    ///         let _ = subscriber;
698    ///     }
699    ///
700    ///     fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
701    ///         self.inner.on_event(event, ctx)
702    ///     }
703    /// }
704    /// let (layer, handle) = layer::mock().on_register_dispatch().run_with_handle();
705    /// let wrap_layer = WrapLayer {
706    ///     inner: layer,
707    ///     _pd: PhantomData::<_>,
708    /// };
709    ///
710    /// let subscriber = tracing_subscriber::registry().with(wrap_layer).set_default();
711    ///
712    /// // The layer's on_register_dispatch is called when the subscriber is set as default
713    /// drop(subscriber);
714    ///
715    /// handle.assert_finished();
716    /// ```
717    ///
718    /// [`Layer::on_register_dispatch`]: tracing_subscriber::layer::Layer::on_register_dispatch
719    pub fn on_register_dispatch(mut self) -> Self {
720        self.expected.push_back(Expect::OnRegisterDispatch);
721        self
722    }
723
724    /// Expects that no further traces are received.
725    ///
726    /// The call to `only` should appear immediately before the final
727    /// call to [`run`] or [`run_with_handle`], as any expectations which
728    /// are added after `only` will not be considered.
729    ///
730    /// # Examples
731    ///
732    /// Consider this simple test. It passes even though we only
733    /// expect a single event, but receive three:
734    ///
735    /// ```
736    /// use tracing_mock::{expect, layer};
737    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
738    ///
739    /// let (layer, handle) = layer::mock()
740    ///     .event(expect::event())
741    ///     .run_with_handle();
742    ///
743    /// let _subscriber = tracing_subscriber::registry()
744    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
745    ///     .set_default();
746    ///
747    /// tracing::info!("a");
748    /// tracing::info!("b");
749    /// tracing::info!("c");
750    ///
751    /// handle.assert_finished();
752    /// ```
753    ///
754    /// After including `only`, the test will fail:
755    ///
756    /// ```should_panic
757    /// use tracing_mock::{expect, layer};
758    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
759    ///
760    /// let (layer, handle) = layer::mock()
761    ///     .event(expect::event())
762    ///     .only()
763    ///     .run_with_handle();
764    ///
765    /// let _subscriber =  tracing_subscriber::registry()
766    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
767    ///     .set_default();
768    ///
769    /// tracing::info!("a");
770    /// tracing::info!("b");
771    /// tracing::info!("c");
772    ///
773    /// handle.assert_finished();
774    /// ```
775    ///
776    /// [`run`]: fn@Self::run
777    /// [`run_with_handle`]: fn@Self::run_with_handle
778    pub fn only(mut self) -> Self {
779        self.expected.push_back(Expect::Nothing);
780        self
781    }
782
783    /// Consume this builder and return a [`MockLayer`] which can
784    /// be set as the default subscriber.
785    ///
786    /// This function is similar to [`run_with_handle`], but it doesn't
787    /// return a [`MockHandle`]. This is useful if the desired
788    /// assertions can be checked externally to the subscriber.
789    ///
790    /// # Examples
791    ///
792    /// The following test is used within the `tracing-subscriber`
793    /// codebase:
794    ///
795    /// ```
796    /// use tracing::Subscriber;
797    /// use tracing_mock::layer;
798    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
799    ///
800    /// let unfiltered = layer::named("unfiltered").run().boxed();
801    /// let info = layer::named("info")
802    ///     .run()
803    ///     .with_filter(tracing_core::LevelFilter::INFO)
804    ///     .boxed();
805    /// let debug = layer::named("debug")
806    ///     .run()
807    ///     .with_filter(tracing_core::LevelFilter::DEBUG)
808    ///     .boxed();
809    ///
810    /// let subscriber = tracing_subscriber::registry().with(vec![unfiltered, info, debug]);
811    ///
812    /// assert_eq!(subscriber.max_level_hint(), None);
813    /// ```
814    ///
815    /// [`MockHandle`]: struct@crate::subscriber::MockHandle
816    /// [`run_with_handle`]: fn@Self::run_with_handle
817    pub fn run(self) -> MockLayer {
818        MockLayer {
819            expected: Arc::new(Mutex::new(self.expected)),
820            name: self.name,
821            current: Mutex::new(Vec::new()),
822        }
823    }
824
825    /// Consume this builder and return a [`MockLayer`] which can
826    /// be set as the default subscriber and a [`MockHandle`] which can
827    /// be used to validate the provided expectations.
828    ///
829    /// # Examples
830    ///
831    /// ```
832    /// use tracing_mock::{expect, layer};
833    /// use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, Layer};
834    ///
835    /// let (layer, handle) = layer::mock()
836    ///     .event(expect::event())
837    ///     .run_with_handle();
838    ///
839    /// let _subscriber =  tracing_subscriber::registry()
840    ///     .with(layer.with_filter(tracing_subscriber::filter::filter_fn(move |_meta| true)))
841    ///     .set_default();
842    ///
843    /// tracing::info!("event");
844    ///
845    /// handle.assert_finished();
846    /// ```
847    ///
848    /// [`MockHandle`]: struct@crate::subscriber::MockHandle
849    /// [`MockLayer`]: struct@crate::layer::MockLayer
850    pub fn run_with_handle(self) -> (MockLayer, MockHandle) {
851        let expected = Arc::new(Mutex::new(self.expected));
852        let handle = MockHandle::new(expected.clone(), self.name.clone());
853        let subscriber = MockLayer {
854            expected,
855            name: self.name,
856            current: Mutex::new(Vec::new()),
857        };
858        (subscriber, handle)
859    }
860}
861
862impl<'a, S> From<&SpanRef<'a, S>> for ActualSpan
863where
864    S: LookupSpan<'a>,
865{
866    fn from(span_ref: &SpanRef<'a, S>) -> Self {
867        Self::new(span_ref.id(), Some(span_ref.metadata()))
868    }
869}
870
871impl MockLayer {
872    fn check_event_scope<C>(
873        &self,
874        current_scope: Option<tracing_subscriber::registry::Scope<'_, C>>,
875        expected_scope: &mut [ExpectedSpan],
876    ) where
877        C: for<'lookup> tracing_subscriber::registry::LookupSpan<'lookup>,
878    {
879        let mut current_scope = current_scope.into_iter().flatten();
880        let mut i = 0;
881        for (expected, actual) in expected_scope.iter_mut().zip(&mut current_scope) {
882            println!(
883                "[{}] event_scope[{}] actual={} ({:?}); expected={}",
884                self.name,
885                i,
886                actual.name(),
887                actual.id(),
888                expected
889            );
890            expected.check(
891                &(&actual).into(),
892                format_args!("the {}th span in the event's scope to be", i),
893                &self.name,
894            );
895            i += 1;
896        }
897        let remaining_expected = &expected_scope[i..];
898        assert!(
899            remaining_expected.is_empty(),
900            "\n[{}] did not observe all expected spans in event scope!\n[{}] missing: {:#?}",
901            self.name,
902            self.name,
903            remaining_expected,
904        );
905        assert!(
906            current_scope.next().is_none(),
907            "\n[{}] did not expect all spans in the actual event scope!",
908            self.name,
909        );
910    }
911}
912
913impl<C> Layer<C> for MockLayer
914where
915    C: Subscriber + for<'a> LookupSpan<'a>,
916{
917    fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) {
918        println!("[{}] on_register_dispatch", self.name);
919        let mut expected = self.expected.lock().unwrap();
920        if let Some(Expect::OnRegisterDispatch) = expected.front() {
921            expected.pop_front();
922        }
923    }
924
925    fn register_callsite(
926        &self,
927        metadata: &'static tracing::Metadata<'static>,
928    ) -> tracing_core::Interest {
929        println!("[{}] register_callsite {:#?}", self.name, metadata);
930        tracing_core::Interest::always()
931    }
932
933    fn on_record(&self, _: &Id, _: &Record<'_>, _: Context<'_, C>) {
934        unimplemented!(
935            "so far, we don't have any tests that need an `on_record` \
936            implementation.\nif you just wrote one that does, feel free to \
937            implement it!"
938        );
939    }
940
941    fn on_event(&self, event: &Event<'_>, cx: Context<'_, C>) {
942        let name = event.metadata().name();
943        println!(
944            "[{}] event: {}; level: {}; target: {}",
945            self.name,
946            name,
947            event.metadata().level(),
948            event.metadata().target(),
949        );
950        match self.expected.lock().unwrap().pop_front() {
951            None => {}
952            Some(Expect::Event(mut expected)) => {
953                expected.check(event, || context_get_ancestry(event, &cx), &self.name);
954
955                if let Some(expected_scope) = expected.scope_mut() {
956                    self.check_event_scope(cx.event_scope(event), expected_scope);
957                }
958            }
959            Some(ex) => ex.bad(&self.name, format_args!("observed event {:#?}", event)),
960        }
961    }
962
963    fn on_follows_from(&self, _span: &Id, _follows: &Id, _: Context<'_, C>) {
964        unimplemented!(
965            "so far, we don't have any tests that need an `on_follows_from` \
966            implementation.\nif you just wrote one that does, feel free to \
967            implement it!"
968        );
969    }
970
971    fn on_new_span(&self, span: &Attributes<'_>, id: &Id, cx: Context<'_, C>) {
972        let meta = span.metadata();
973        println!(
974            "[{}] new_span: name={:?}; target={:?}; id={:?};",
975            self.name,
976            meta.name(),
977            meta.target(),
978            id
979        );
980        let mut expected = self.expected.lock().unwrap();
981        let was_expected = matches!(expected.front(), Some(Expect::NewSpan(_)));
982        if was_expected {
983            if let Expect::NewSpan(mut expected) = expected.pop_front().unwrap() {
984                expected.check(span, || context_get_ancestry(span, &cx), &self.name);
985            }
986        }
987    }
988
989    fn on_enter(&self, id: &Id, cx: Context<'_, C>) {
990        let span = cx
991            .span(id)
992            .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id));
993        println!("[{}] enter: {}; id={:?};", self.name, span.name(), id);
994        match self.expected.lock().unwrap().pop_front() {
995            None => {}
996            Some(Expect::Enter(ref expected_span)) => {
997                expected_span.check(&(&span).into(), "to enter", &self.name);
998            }
999            Some(ex) => ex.bad(&self.name, format_args!("entered span {:?}", span.name())),
1000        }
1001        self.current.lock().unwrap().push(id.clone());
1002    }
1003
1004    fn on_exit(&self, id: &Id, cx: Context<'_, C>) {
1005        if std::thread::panicking() {
1006            // `exit()` can be called in `drop` impls, so we must guard against
1007            // double panics.
1008            println!("[{}] exit {:?} while panicking", self.name, id);
1009            return;
1010        }
1011        let span = cx
1012            .span(id)
1013            .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id));
1014        println!("[{}] exit: {}; id={:?};", self.name, span.name(), id);
1015        match self.expected.lock().unwrap().pop_front() {
1016            None => {}
1017            Some(Expect::Exit(ref expected_span)) => {
1018                expected_span.check(&(&span).into(), "to exit", &self.name);
1019                let curr = self.current.lock().unwrap().pop();
1020                assert_eq!(
1021                    Some(id),
1022                    curr.as_ref(),
1023                    "[{}] exited span {:?}, but the current span was {:?}",
1024                    self.name,
1025                    span.name(),
1026                    curr.as_ref().and_then(|id| cx.span(id)).map(|s| s.name())
1027                );
1028            }
1029            Some(ex) => ex.bad(&self.name, format_args!("exited span {:?}", span.name())),
1030        };
1031    }
1032
1033    fn on_close(&self, id: Id, cx: Context<'_, C>) {
1034        if std::thread::panicking() {
1035            // `try_close` can be called in `drop` impls, so we must guard against
1036            // double panics.
1037            println!("[{}] close {:?} while panicking", self.name, id);
1038            return;
1039        }
1040        let span = cx.span(&id);
1041        let name = span.as_ref().map(|span| {
1042            println!("[{}] close_span: {}; id={:?};", self.name, span.name(), id,);
1043            span.name()
1044        });
1045        if name.is_none() {
1046            println!("[{}] drop_span: id={:?}", self.name, id);
1047        }
1048        if let Ok(mut expected) = self.expected.try_lock() {
1049            let was_expected = match expected.front() {
1050                Some(Expect::DropSpan(ref expected_span)) => {
1051                    // Don't assert if this function was called while panicking,
1052                    // as failing the assertion can cause a double panic.
1053                    if !::std::thread::panicking() {
1054                        if let Some(ref span) = span {
1055                            expected_span.check(&span.into(), "to close a span", &self.name);
1056                        }
1057                    }
1058                    true
1059                }
1060                Some(Expect::Event(_)) => {
1061                    if !::std::thread::panicking() {
1062                        panic!(
1063                            "[{}] expected an event, but dropped span {} (id={:?}) instead",
1064                            self.name,
1065                            name.unwrap_or("<unknown name>"),
1066                            id
1067                        );
1068                    }
1069                    true
1070                }
1071                _ => false,
1072            };
1073            if was_expected {
1074                expected.pop_front();
1075            }
1076        }
1077    }
1078
1079    fn on_id_change(&self, _old: &Id, _new: &Id, _ctx: Context<'_, C>) {
1080        panic!("well-behaved subscribers should never do this to us, lol");
1081    }
1082}
1083
1084fn context_get_ancestry<C>(item: impl HasAncestry, ctx: &Context<'_, C>) -> ActualAncestry
1085where
1086    C: Subscriber + for<'a> LookupSpan<'a>,
1087{
1088    get_ancestry(
1089        item,
1090        || ctx.lookup_current().map(|s| s.id()),
1091        |span_id| ctx.span(span_id).map(|span| (&span).into()),
1092    )
1093}
1094
1095impl fmt::Debug for MockLayer {
1096    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097        let mut s = f.debug_struct("ExpectSubscriber");
1098        s.field("name", &self.name);
1099
1100        if let Ok(expected) = self.expected.try_lock() {
1101            s.field("expected", &expected);
1102        } else {
1103            s.field("expected", &format_args!("<locked>"));
1104        }
1105
1106        if let Ok(current) = self.current.try_lock() {
1107            s.field("current", &format_args!("{:?}", &current));
1108        } else {
1109            s.field("current", &format_args!("<locked>"));
1110        }
1111
1112        s.finish()
1113    }
1114}