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!("{:?}", ¤t));
1108 } else {
1109 s.field("current", &format_args!("<locked>"));
1110 }
1111
1112 s.finish()
1113 }
1114}