tracing_mock/
subscriber.rs

1//! An implementation of the [`Subscriber`] trait to receive and validate
2//! `tracing` data.
3//!
4//! The [`MockSubscriber`] is the central component of this crate. The
5//! `MockSubscriber` has expectations set on it which are later
6//! validated as the code under test is run.
7//!
8//! # Examples
9//!
10//! ```
11//! use tracing_mock::{expect, subscriber, field};
12//!
13//! let (subscriber, handle) = subscriber::mock()
14//!     // Expect a single event with a specified message
15//!     .event(expect::event().with_fields(expect::msg("droids")))
16//!     .only()
17//!     .run_with_handle();
18//!
19//! // Use `with_default` to apply the `MockSubscriber` for the duration
20//! // of the closure - this is what we are testing.
21//! tracing::subscriber::with_default(subscriber, || {
22//!     // These *are* the droids we are looking for
23//!     tracing::info!("droids");
24//! });
25//!
26//! // Use the handle to check the assertions. This line will panic if an
27//! // assertion is not met.
28//! handle.assert_finished();
29//! ```
30//!
31//! A more complex example may consider multiple spans and events with
32//! their respective fields:
33//!
34//! ```
35//! use tracing_mock::{expect, subscriber, field};
36//!
37//! let span = expect::span()
38//!     .named("my_span");
39//! let (subscriber, handle) = subscriber::mock()
40//!     // Enter a matching span
41//!     .enter(&span)
42//!     // Record an event with message "subscriber parting message"
43//!     .event(expect::event().with_fields(expect::msg("subscriber parting message")))
44//!     // Record a value for the field `parting` on a matching span
45//!     .record(&span, expect::field("parting").with_value(&"goodbye world!"))
46//!     // Exit a matching span
47//!     .exit(span)
48//!     // Expect no further messages to be recorded
49//!     .only()
50//!     // Return the subscriber and handle
51//!     .run_with_handle();
52//!
53//! // Use `with_default` to apply the `MockSubscriber` for the duration
54//! // of the closure - this is what we are testing.
55//! tracing::subscriber::with_default(subscriber, || {
56//!     let span = tracing::trace_span!(
57//!         "my_span",
58//!         greeting = "hello world",
59//!         parting = tracing::field::Empty
60//!     );
61//!
62//!     let _guard = span.enter();
63//!     tracing::info!("subscriber parting message");
64//!     let parting = "goodbye world!";
65//!
66//!     span.record("parting", &parting);
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, subscriber, field};
79//!
80//! let span = expect::span()
81//!     .named("my_span");
82//! let (subscriber, handle) = subscriber::mock()
83//!     .enter(&span)
84//!     .event(expect::event().with_fields(expect::msg("collect parting message")))
85//!     .record(&span, expect::field("parting").with_value(&"goodbye world!"))
86//!     .exit(span)
87//!     .only()
88//!     .run_with_handle();
89//!
90//! // Use `with_default` to apply the `MockSubscriber` for the duration
91//! // of the closure - this is what we are testing.
92//! tracing::subscriber::with_default(subscriber, || {
93//!     let span = tracing::trace_span!(
94//!         "my_span",
95//!         greeting = "hello world",
96//!         parting = tracing::field::Empty
97//!     );
98//!
99//!     // Don't enter the span.
100//!     // let _guard = span.enter();
101//!     tracing::info!("subscriber parting message");
102//!     let parting = "goodbye world!";
103//!
104//!     span.record("parting", &parting);
105//! });
106//!
107//! // Use the handle to check the assertions. This line will panic if an
108//! // assertion is not met.
109//! handle.assert_finished();
110//! ```
111//!
112//! This will result in an error message such as the following:
113//!
114//! ```text
115//! thread 'main' panicked at '
116//! [main] expected to enter a span named `my_span`
117//! [main] but instead observed event Event {
118//!     fields: ValueSet {
119//!         message: subscriber parting message,
120//!         callsite: Identifier(0x10eda3278),
121//!     },
122//!     metadata: Metadata {
123//!         name: "event src/subscriber.rs:27",
124//!         target: "rust_out",
125//!         level: Level(
126//!             Info,
127//!         ),
128//!         module_path: "rust_out",
129//!         location: src/subscriber.rs:27,
130//!         fields: {message},
131//!         callsite: Identifier(0x10eda3278),
132//!         kind: Kind(EVENT),
133//!     },
134//!     parent: Current,
135//! }', tracing/tracing-mock/src/expect.rs:59:33
136//! ```
137//!
138//! [`Subscriber`]: trait@tracing::Subscriber
139//! [`MockSubscriber`]: struct@crate::subscriber::MockSubscriber
140use std::{
141    collections::{HashMap, VecDeque},
142    sync::{
143        atomic::{AtomicUsize, Ordering},
144        Arc, Mutex,
145    },
146    thread,
147};
148use tracing::{
149    level_filters::LevelFilter,
150    span::{self, Attributes, Id},
151    subscriber::Interest,
152    Event, Metadata, Subscriber,
153};
154
155use crate::{
156    ancestry::get_ancestry,
157    event::ExpectedEvent,
158    expect::Expect,
159    field::ExpectedFields,
160    span::{ActualSpan, ExpectedSpan, NewSpan},
161};
162
163pub(crate) struct SpanState {
164    id: Id,
165    name: &'static str,
166    refs: usize,
167    meta: &'static Metadata<'static>,
168}
169
170impl From<&SpanState> for ActualSpan {
171    fn from(span_state: &SpanState) -> Self {
172        Self::new(span_state.id.clone(), Some(span_state.meta))
173    }
174}
175
176struct Running<F: Fn(&Metadata<'_>) -> bool> {
177    spans: Mutex<HashMap<Id, SpanState>>,
178    expected: Arc<Mutex<VecDeque<Expect>>>,
179    current: Mutex<Vec<Id>>,
180    ids: AtomicUsize,
181    max_level: Option<LevelFilter>,
182    filter: F,
183    name: String,
184}
185
186/// A subscriber which can validate received traces.
187///
188/// For a detailed description and examples see the documentation
189/// for the methods and the [`subscriber`] module.
190///
191/// [`subscriber`]: mod@crate::subscriber
192#[derive(Debug)]
193pub struct MockSubscriber<F: Fn(&Metadata<'_>) -> bool> {
194    expected: VecDeque<Expect>,
195    max_level: Option<LevelFilter>,
196    filter: F,
197    name: String,
198}
199
200/// A handle which is used to invoke validation of expectations.
201///
202/// The handle is currently only used to assert that all the expected
203/// events and spans were seen.
204///
205/// For additional information and examples, see the [`subscriber`]
206/// module documentation.
207///
208/// [`subscriber`]: mod@crate::subscriber
209#[derive(Debug)]
210pub struct MockHandle(Arc<Mutex<VecDeque<Expect>>>, String);
211
212/// Create a new [`MockSubscriber`].
213///
214/// For additional information and examples, see the [`subscriber`]
215/// module and [`MockSubscriber`] documentation.
216///
217/// # Examples
218///
219///
220/// ```
221/// use tracing_mock::{expect, subscriber, field};
222///
223/// let span = expect::span()
224///     .named("my_span");
225/// let (subscriber, handle) = subscriber::mock()
226///     // Enter a matching span
227///     .enter(&span)
228///     // Record an event with message "subscriber parting message"
229///     .event(expect::event().with_fields(expect::msg("subscriber parting message")))
230///     // Record a value for the field `parting` on a matching span
231///     .record(&span, expect::field("parting").with_value(&"goodbye world!"))
232///     // Exit a matching span
233///     .exit(span)
234///     // Expect no further messages to be recorded
235///     .only()
236///     // Return the subscriber and handle
237///     .run_with_handle();
238///
239/// // Use `with_default` to apply the `MockSubscriber` for the duration
240/// // of the closure - this is what we are testing.
241/// tracing::subscriber::with_default(subscriber, || {
242///     let span = tracing::trace_span!(
243///         "my_span",
244///         greeting = "hello world",
245///         parting = tracing::field::Empty
246///     );
247///
248///     let _guard = span.enter();
249///     tracing::info!("subscriber parting message");
250///     let parting = "goodbye world!";
251///
252///     span.record("parting", &parting);
253/// });
254///
255/// // Use the handle to check the assertions. This line will panic if an
256/// // assertion is not met.
257/// handle.assert_finished();
258/// ```
259///
260/// [`subscriber`]: mod@crate::subscriber
261#[must_use]
262pub fn mock() -> MockSubscriber<fn(&Metadata<'_>) -> bool> {
263    MockSubscriber {
264        expected: VecDeque::new(),
265        filter: (|_: &Metadata<'_>| true) as for<'r, 's> fn(&'r Metadata<'s>) -> _,
266        max_level: None,
267        name: thread::current()
268            .name()
269            .unwrap_or("mock_subscriber")
270            .to_string(),
271    }
272}
273
274impl<F> MockSubscriber<F>
275where
276    F: Fn(&Metadata<'_>) -> bool + 'static,
277{
278    /// Overrides the name printed by the mock subscriber's debugging output.
279    ///
280    /// The debugging output is displayed if the test panics, or if the test is
281    /// run with `--nocapture`.
282    ///
283    /// By default, the mock subscriber's name is the  name of the test
284    /// (*technically*, the name of the thread where it was created, which is
285    /// the name of the test unless tests are run with `--test-threads=1`).
286    /// When a test has only one mock subscriber, this is sufficient. However,
287    /// some tests may include multiple subscribers, in order to test
288    /// interactions between multiple subscribers. In that case, it can be
289    /// helpful to give each subscriber a separate name to distinguish where the
290    /// debugging output comes from.
291    ///
292    /// # Examples
293    ///
294    /// In the following example, we create 2 subscribers, both
295    /// expecting to receive an event. As we only record a single
296    /// event, the test will fail:
297    ///
298    /// ```should_panic
299    /// use tracing_mock::{expect, subscriber};
300    ///
301    /// let (subscriber_1, handle_1) = subscriber::mock()
302    ///     .named("subscriber-1")
303    ///     .event(expect::event())
304    ///     .run_with_handle();
305    ///
306    /// let (subscriber_2, handle_2) = subscriber::mock()
307    ///     .named("subscriber-2")
308    ///     .event(expect::event())
309    ///     .run_with_handle();
310    ///
311    /// let _guard = tracing::subscriber::set_default(subscriber_2);
312    ///
313    /// tracing::subscriber::with_default(subscriber_1, || {
314    ///     tracing::info!("a");
315    /// });
316    ///
317    /// handle_1.assert_finished();
318    /// handle_2.assert_finished();
319    /// ```
320    ///
321    /// In the test output, we see that the subscriber which didn't
322    /// received the event was the one named `subscriber-2`, which is
323    /// correct as the subscriber named `subscriber-1` was the default
324    /// when the event was recorded:
325    ///
326    /// ```text
327    /// [subscriber-2] more notifications expected: [
328    ///     Event(
329    ///         MockEvent,
330    ///     ),
331    /// ]', tracing-mock/src/subscriber.rs:1276:13
332    /// ```
333    pub fn named(self, name: impl ToString) -> Self {
334        Self {
335            name: name.to_string(),
336            ..self
337        }
338    }
339
340    /// Adds an expectation that an event matching the [`ExpectedEvent`]
341    /// will be recorded next.
342    ///
343    /// The `event` can be a default mock which will match any event
344    /// (`expect::event()`) or can include additional expectations.
345    /// See the [`ExpectedEvent`] documentation for more details.
346    ///
347    /// If an event is recorded that doesn't match the `ExpectedEvent`,
348    /// or if something else (such as entering a span) is recorded
349    /// first, then the expectation will fail.
350    ///
351    /// # Examples
352    ///
353    /// ```
354    /// use tracing_mock::{expect, subscriber};
355    ///
356    /// let (subscriber, handle) = subscriber::mock()
357    ///     .event(expect::event())
358    ///     .run_with_handle();
359    ///
360    /// tracing::subscriber::with_default(subscriber, || {
361    ///     tracing::info!("a");
362    /// });
363    ///
364    /// handle.assert_finished();
365    /// ```
366    ///
367    /// A span is entered before the event, causing the test to fail:
368    ///
369    /// ```should_panic
370    /// use tracing_mock::{expect, subscriber};
371    ///
372    /// let (subscriber, handle) = subscriber::mock()
373    ///     .event(expect::event())
374    ///     .run_with_handle();
375    ///
376    /// tracing::subscriber::with_default(subscriber, || {
377    ///     let span = tracing::info_span!("span");
378    ///     let _guard = span.enter();
379    ///     tracing::info!("a");
380    /// });
381    ///
382    /// handle.assert_finished();
383    /// ```
384    pub fn event(mut self, event: ExpectedEvent) -> Self {
385        self.expected.push_back(Expect::Event(event));
386        self
387    }
388
389    /// Adds an expectation that the creation of a span will be
390    /// recorded next.
391    ///
392    /// This function accepts `Into<NewSpan>` instead of
393    /// [`ExpectedSpan`] directly, so it can be used to test
394    /// span fields and the span parent. This is because a
395    /// subscriber only receives the span fields and parent when
396    /// a span is created, not when it is entered.
397    ///
398    /// The new span doesn't need to be entered for this expectation
399    /// to succeed.
400    ///
401    /// If a span is recorded that doesn't match the `ExpectedSpan`,
402    /// or if something else (such as an event) is recorded first,
403    /// then the expectation will fail.
404    ///
405    /// # Examples
406    ///
407    /// ```
408    /// use tracing_mock::{expect, subscriber};
409    ///
410    /// let span = expect::span()
411    ///     .at_level(tracing::Level::INFO)
412    ///     .named("the span we're testing")
413    ///     .with_fields(expect::field("testing").with_value(&"yes"));
414    /// let (subscriber, handle) = subscriber::mock()
415    ///     .new_span(span)
416    ///     .run_with_handle();
417    ///
418    /// tracing::subscriber::with_default(subscriber, || {
419    ///     _ = tracing::info_span!("the span we're testing", testing = "yes");
420    /// });
421    ///
422    /// handle.assert_finished();
423    /// ```
424    ///
425    /// An event is recorded before the span is created, causing the
426    /// test to fail:
427    ///
428    /// ```should_panic
429    /// use tracing_mock::{expect, subscriber};
430    ///
431    /// let span = expect::span()
432    ///     .at_level(tracing::Level::INFO)
433    ///     .named("the span we're testing")
434    ///     .with_fields(expect::field("testing").with_value(&"yes"));
435    /// let (subscriber, handle) = subscriber::mock()
436    ///     .new_span(span)
437    ///     .run_with_handle();
438    ///
439    /// tracing::subscriber::with_default(subscriber, || {
440    ///     tracing::info!("an event");
441    ///     _ = tracing::info_span!("the span we're testing", testing = "yes");
442    /// });
443    ///
444    /// handle.assert_finished();
445    /// ```
446    pub fn new_span<I>(mut self, new_span: I) -> Self
447    where
448        I: Into<NewSpan>,
449    {
450        self.expected.push_back(Expect::NewSpan(new_span.into()));
451        self
452    }
453
454    /// Adds an expectation that entering a span matching the
455    /// [`ExpectedSpan`] will be recorded next.
456    ///
457    /// This expectation is generally accompanied by a call to
458    /// [`exit`] as well. If used together with [`only`], this
459    /// is necessary.
460    ///
461    /// If the span that is entered doesn't match the [`ExpectedSpan`],
462    /// or if something else (such as an event) is recorded first,
463    /// then the expectation will fail.
464    ///
465    /// # Examples
466    ///
467    /// ```
468    /// use tracing_mock::{expect, subscriber};
469    ///
470    /// let span = expect::span()
471    ///     .at_level(tracing::Level::INFO)
472    ///     .named("the span we're testing");
473    /// let (subscriber, handle) = subscriber::mock()
474    ///     .enter(&span)
475    ///     .exit(&span)
476    ///     .only()
477    ///     .run_with_handle();
478    ///
479    /// tracing::subscriber::with_default(subscriber, || {
480    ///     let span = tracing::info_span!("the span we're testing");
481    ///     let _entered = span.enter();
482    /// });
483    ///
484    /// handle.assert_finished();
485    /// ```
486    ///
487    /// An event is recorded before the span is entered, causing the
488    /// test to fail:
489    ///
490    /// ```should_panic
491    /// use tracing_mock::{expect, subscriber};
492    ///
493    /// let span = expect::span()
494    ///     .at_level(tracing::Level::INFO)
495    ///     .named("the span we're testing");
496    /// let (subscriber, handle) = subscriber::mock()
497    ///     .enter(&span)
498    ///     .exit(&span)
499    ///     .only()
500    ///     .run_with_handle();
501    ///
502    /// tracing::subscriber::with_default(subscriber, || {
503    ///     tracing::info!("an event");
504    ///     let span = tracing::info_span!("the span we're testing");
505    ///     let _entered = span.enter();
506    /// });
507    ///
508    /// handle.assert_finished();
509    /// ```
510    ///
511    /// [`exit`]: fn@Self::exit
512    /// [`only`]: fn@Self::only
513    pub fn enter<S>(mut self, span: S) -> Self
514    where
515        S: Into<ExpectedSpan>,
516    {
517        self.expected.push_back(Expect::Enter(span.into()));
518        self
519    }
520
521    /// Adds ab expectation that exiting a span matching the
522    /// [`ExpectedSpan`] will be recorded next.
523    ///
524    /// As a span may be entered and exited multiple times,
525    /// this is different from the span being closed. In
526    /// general [`enter`] and `exit` should be paired.
527    ///
528    /// If the span that is exited doesn't match the [`ExpectedSpan`],
529    /// or if something else (such as an event) is recorded first,
530    /// then the expectation will fail.
531    ///
532    /// # Examples
533    ///
534    /// ```
535    /// use tracing_mock::{expect, subscriber};
536    ///
537    /// let span = expect::span()
538    ///     .at_level(tracing::Level::INFO)
539    ///     .named("the span we're testing");
540    /// let (subscriber, handle) = subscriber::mock()
541    ///     .enter(&span)
542    ///     .exit(&span)
543    ///     .run_with_handle();
544    ///
545    /// tracing::subscriber::with_default(subscriber, || {
546    ///     let span = tracing::info_span!("the span we're testing");
547    ///     let _entered = span.enter();
548    /// });
549    ///
550    /// handle.assert_finished();
551    /// ```
552    ///
553    /// An event is recorded before the span is exited, causing the
554    /// test to fail:
555    ///
556    /// ```should_panic
557    /// use tracing_mock::{expect, subscriber};
558    ///
559    /// let span = expect::span()
560    ///     .at_level(tracing::Level::INFO)
561    ///     .named("the span we're testing");
562    /// let (subscriber, handle) = subscriber::mock()
563    ///     .enter(&span)
564    ///     .exit(&span)
565    ///     .run_with_handle();
566    ///
567    /// tracing::subscriber::with_default(subscriber, || {
568    ///     let span = tracing::info_span!("the span we're testing");
569    ///     let _entered = span.enter();
570    ///     tracing::info!("an event");
571    /// });
572    ///
573    /// handle.assert_finished();
574    /// ```
575    ///
576    /// [`enter`]: fn@Self::enter
577    pub fn exit<S>(mut self, span: S) -> Self
578    where
579        S: Into<ExpectedSpan>,
580    {
581        self.expected.push_back(Expect::Exit(span.into()));
582        self
583    }
584
585    /// Adds an expectation that cloning a span matching the
586    /// [`ExpectedSpan`] will be recorded next.
587    ///
588    /// The cloned span does need to be entered.
589    ///
590    /// If the span that is cloned doesn't match the [`ExpectedSpan`],
591    /// or if something else (such as an event) is recorded first,
592    /// then the expectation will fail.
593    ///
594    /// # Examples
595    ///
596    /// ```
597    /// use tracing_mock::{expect, subscriber};
598    ///
599    /// let span = expect::span()
600    ///     .at_level(tracing::Level::INFO)
601    ///     .named("the span we're testing");
602    /// let (subscriber, handle) = subscriber::mock()
603    ///     .clone_span(span)
604    ///     .run_with_handle();
605    ///
606    /// tracing::subscriber::with_default(subscriber, || {
607    ///     let span = tracing::info_span!("the span we're testing");
608    ///     _ = span.clone();
609    /// });
610    ///
611    /// handle.assert_finished();
612    /// ```
613    ///
614    /// An event is recorded before the span is cloned, causing the
615    /// test to fail:
616    ///
617    /// ```should_panic
618    /// use tracing_mock::{expect, subscriber};
619    ///
620    /// let span = expect::span()
621    ///     .at_level(tracing::Level::INFO)
622    ///     .named("the span we're testing");
623    /// let (subscriber, handle) = subscriber::mock()
624    ///     .clone_span(span)
625    ///     .run_with_handle();
626    ///
627    /// tracing::subscriber::with_default(subscriber, || {
628    ///     let span = tracing::info_span!("the span we're testing");
629    ///     tracing::info!("an event");
630    ///     _ = span.clone();
631    /// });
632    ///
633    /// handle.assert_finished();
634    /// ```
635    pub fn clone_span<S>(mut self, span: S) -> Self
636    where
637        S: Into<ExpectedSpan>,
638    {
639        self.expected.push_back(Expect::CloneSpan(span.into()));
640        self
641    }
642
643    /// **This method is deprecated.**
644    ///
645    /// Adds an expectation that a span matching the [`ExpectedSpan`]
646    /// getting dropped via the deprecated function
647    /// [`Subscriber::drop_span`] will be recorded next.
648    ///
649    /// Instead [`Subscriber::try_close`] should be used on the subscriber
650    /// and should be asserted with `close_span` (which hasn't been
651    /// implemented yet, but will be done as part of #539).
652    ///
653    /// [`Subscriber::drop_span`]: fn@tracing::Subscriber::drop_span
654    #[allow(deprecated)]
655    pub fn drop_span<S>(mut self, span: S) -> Self
656    where
657        S: Into<ExpectedSpan>,
658    {
659        self.expected.push_back(Expect::DropSpan(span.into()));
660        self
661    }
662
663    /// Adds an expectation that a `follows_from` relationship will be
664    /// recorded next. Specifically that a span matching `consequence`
665    /// follows from a span matching `cause`.
666    ///
667    /// For further details on what this causal relationship means, see
668    /// [`Span::follows_from`].
669    ///
670    /// If either of the 2 spans don't match their respective
671    /// [`ExpectedSpan`] or if something else (such as an event) is
672    /// recorded first, then the expectation will fail.
673    ///
674    /// **Note**: The 2 spans, `consequence` and `cause` are matched
675    /// by `name` only.
676    ///
677    /// # Examples
678    ///
679    /// ```
680    /// use tracing_mock::{expect, subscriber};
681    ///
682    /// let cause = expect::span().named("cause");
683    /// let consequence = expect::span().named("consequence");
684    ///
685    /// let (subscriber, handle) = subscriber::mock()
686    ///     .follows_from(consequence, cause)
687    ///     .run_with_handle();
688    ///
689    /// tracing::subscriber::with_default(subscriber, || {
690    ///     let cause = tracing::info_span!("cause");
691    ///     let consequence = tracing::info_span!("consequence");
692    ///
693    ///     consequence.follows_from(&cause);
694    /// });
695    ///
696    /// handle.assert_finished();
697    /// ```
698    ///
699    /// The `cause` span doesn't match, it is actually recorded at
700    /// `Level::WARN` instead of the expected `Level::INFO`, causing
701    /// this test to fail:
702    ///
703    /// ```should_panic
704    /// use tracing_mock::{expect, subscriber};
705    ///
706    /// let cause = expect::span().named("cause");
707    /// let consequence = expect::span().named("consequence");
708    ///
709    /// let (subscriber, handle) = subscriber::mock()
710    ///     .follows_from(consequence, cause)
711    ///     .run_with_handle();
712    ///
713    /// tracing::subscriber::with_default(subscriber, || {
714    ///     let cause = tracing::info_span!("another cause");
715    ///     let consequence = tracing::info_span!("consequence");
716    ///
717    ///     consequence.follows_from(&cause);
718    /// });
719    ///
720    /// handle.assert_finished();
721    /// ```
722    ///
723    /// [`Span::follows_from`]: fn@tracing::Span::follows_from
724    pub fn follows_from<S1, S2>(mut self, consequence: S1, cause: S2) -> Self
725    where
726        S1: Into<ExpectedSpan>,
727        S2: Into<ExpectedSpan>,
728    {
729        self.expected.push_back(Expect::FollowsFrom {
730            consequence: consequence.into(),
731            cause: cause.into(),
732        });
733        self
734    }
735
736    /// Adds an expectation that `fields` are recorded on a span
737    /// matching the [`ExpectedSpan`] will be recorded next.
738    ///
739    /// For further information on how to specify the expected
740    /// fields, see the documentation on the [`field`] module.
741    ///
742    /// If either the span doesn't match the [`ExpectedSpan`], the
743    /// fields don't match the expected fields, or if something else
744    /// (such as an event) is recorded first, then the expectation
745    /// will fail.
746    ///
747    /// # Examples
748    ///
749    /// ```
750    /// use tracing_mock::{expect, subscriber};
751    ///
752    /// let span = expect::span()
753    ///     .named("my_span");
754    /// let (subscriber, handle) = subscriber::mock()
755    ///     .record(span, expect::field("parting").with_value(&"goodbye world!"))
756    ///     .run_with_handle();
757    ///
758    /// tracing::subscriber::with_default(subscriber, || {
759    ///     let span = tracing::trace_span!(
760    ///         "my_span",
761    ///         greeting = "hello world",
762    ///         parting = tracing::field::Empty
763    ///     );
764    ///     span.record("parting", "goodbye world!");
765    /// });
766    ///
767    /// handle.assert_finished();
768    /// ```
769    ///
770    /// The value of the recorded field doesn't match the expectation,
771    /// causing the test to fail:
772    ///
773    /// ```should_panic
774    /// use tracing_mock::{expect, subscriber};
775    ///
776    /// let span = expect::span()
777    ///     .named("my_span");
778    /// let (subscriber, handle) = subscriber::mock()
779    ///     .record(span, expect::field("parting").with_value(&"goodbye world!"))
780    ///     .run_with_handle();
781    ///
782    /// tracing::subscriber::with_default(subscriber, || {
783    ///     let span = tracing::trace_span!(
784    ///         "my_span",
785    ///         greeting = "hello world",
786    ///         parting = tracing::field::Empty
787    ///     );
788    ///     span.record("parting", "goodbye universe!");
789    /// });
790    ///
791    /// handle.assert_finished();
792    /// ```
793    ///
794    /// [`field`]: mod@crate::field
795    pub fn record<S, I>(mut self, span: S, fields: I) -> Self
796    where
797        S: Into<ExpectedSpan>,
798        I: Into<ExpectedFields>,
799    {
800        self.expected
801            .push_back(Expect::Visit(span.into(), fields.into()));
802        self
803    }
804
805    /// Adds an expectation that [`Subscriber::on_register_dispatch`] will
806    /// be called next.
807    ///
808    /// **Note**: This expectation is usually fulfilled automatically when
809    /// a subscriber is set as the default via [`tracing::subscriber::with_default`]
810    /// or [`tracing::subscriber::set_global_default`], so explicitly expecting
811    /// this is not usually necessary. However, it may be useful when testing
812    /// custom subscriber implementations that manually call `on_register_dispatch`.
813    ///
814    /// # Examples
815    ///
816    /// ```
817    /// use tracing_mock::{expect, subscriber};
818    ///
819    /// let (subscriber, handle) = subscriber::mock()
820    ///     .on_register_dispatch()
821    ///     .run_with_handle();
822    ///
823    /// tracing::subscriber::with_default(subscriber, || {
824    ///     // The subscriber's on_register_dispatch was called when it was set as default
825    /// });
826    ///
827    /// handle.assert_finished();
828    /// ```
829    ///
830    ///
831    /// ```should_panic
832    /// use tracing_mock::{subscriber};
833    ///
834    /// struct WrapSubscriber<S: tracing::Subscriber> {
835    ///     inner: S,
836    /// }
837    ///
838    /// impl<S: tracing::Subscriber> tracing::Subscriber for WrapSubscriber<S> {
839    /// #     fn enabled(&self, metadata: &tracing::Metadata<'_>) -> bool {
840    /// #         self.inner.enabled(metadata)
841    /// #     }
842    /// #     fn new_span(&self, span: &tracing_core::span::Attributes<'_>) -> tracing_core::span::Id {
843    /// #         self.inner.new_span(span)
844    /// #     }
845    /// #     fn record(&self, span: &tracing_core::span::Id, values: &tracing_core::span::Record<'_>) {
846    /// #         self.inner.record(span, values)
847    /// #     }
848    /// #     fn record_follows_from(
849    /// #         &self,
850    /// #         span: &tracing_core::span::Id,
851    /// #         follows: &tracing_core::span::Id,
852    /// #     ) {
853    /// #         self.inner.record_follows_from(span, follows)
854    /// #     }
855    /// #     fn event(&self, event: &tracing::Event<'_>) {
856    /// #         self.inner.event(event)
857    /// #     }
858    /// #     fn enter(&self, span: &tracing_core::span::Id) {
859    /// #         self.inner.enter(span)
860    /// #     }
861    /// #     fn exit(&self, span: &tracing_core::span::Id) {
862    /// #         self.inner.exit(span)
863    /// #     }
864    ///     // All other Subscriber methods implemented to forward correctly.
865    ///
866    ///     fn on_register_dispatch(&self, subscriber: &tracing::Dispatch) {
867    ///         // Doesn't forward to `self.inner`
868    ///         let _ = subscriber;
869    ///     }
870    /// }
871    ///
872    /// let (subscriber, handle) = subscriber::mock().on_register_dispatch().run_with_handle();
873    /// let wrap_subscriber = WrapSubscriber { inner: subscriber };
874    ///
875    /// tracing::subscriber::with_default(wrap_subscriber, || {
876    ///     // The subscriber's on_register_dispatch is called when set as default
877    /// });
878    ///
879    /// handle.assert_finished();
880    /// ```
881    ///
882    /// [`Subscriber::on_register_dispatch`]: tracing::Subscriber::on_register_dispatch
883    pub fn on_register_dispatch(mut self) -> Self {
884        self.expected.push_back(Expect::OnRegisterDispatch);
885        self
886    }
887
888    /// Filter the traces evaluated by the `MockSubscriber`.
889    ///
890    /// The filter will be applied to all traces received before
891    /// any validation occurs - so its position in the call chain
892    /// is not important. The filter does not perform any validation
893    /// itself.
894    ///
895    /// # Examples
896    ///
897    /// ```
898    /// use tracing_mock::{expect, subscriber};
899    ///
900    /// let (subscriber, handle) = subscriber::mock()
901    ///     .with_filter(|meta| meta.level() <= &tracing::Level::WARN)
902    ///     .event(expect::event())
903    ///     .only()
904    ///     .run_with_handle();
905    ///
906    /// tracing::subscriber::with_default(subscriber, || {
907    ///     tracing::info!("a");
908    ///     tracing::warn!("b");
909    /// });
910    ///
911    /// handle.assert_finished();
912    /// ```
913    pub fn with_filter<G>(self, filter: G) -> MockSubscriber<G>
914    where
915        G: Fn(&Metadata<'_>) -> bool + 'static,
916    {
917        MockSubscriber {
918            expected: self.expected,
919            filter,
920            max_level: self.max_level,
921            name: self.name,
922        }
923    }
924
925    /// Sets the max level that will be provided to the `tracing`
926    /// system.
927    ///
928    /// This method can be used to test the internals of `tracing`,
929    /// but it is also useful to filter out traces on more verbose
930    /// levels if you only want to verify above a certain level.
931    ///
932    /// **Note**: this value determines a global filter, if
933    /// `with_max_level_hint` is called on multiple subscribers, the
934    /// global filter will be the least restrictive of all subscribers.
935    /// To filter the events evaluated by a specific `MockSubscriber`,
936    /// use [`with_filter`] instead.
937    ///
938    /// # Examples
939    ///
940    /// ```
941    /// use tracing_mock::{expect, subscriber};
942    ///
943    /// let (subscriber, handle) = subscriber::mock()
944    ///     .with_max_level_hint(tracing::Level::INFO)
945    ///     .event(expect::event().at_level(tracing::Level::INFO))
946    ///     .only()
947    ///     .run_with_handle();
948    ///
949    /// tracing::subscriber::with_default(subscriber, || {
950    ///     tracing::debug!("a message we don't care about");
951    ///     tracing::info!("a message we want to validate");
952    /// });
953    ///
954    /// handle.assert_finished();
955    /// ```
956    ///
957    /// [`with_filter`]: fn@Self::with_filter
958    pub fn with_max_level_hint(self, hint: impl Into<LevelFilter>) -> Self {
959        Self {
960            max_level: Some(hint.into()),
961            ..self
962        }
963    }
964
965    /// Expects that no further traces are received.
966    ///
967    /// The call to `only` should appear immediately before the final
968    /// call to `run` or `run_with_handle`, as any expectations which
969    /// are added after `only` will not be considered.
970    ///
971    /// # Examples
972    ///
973    /// Consider this simple test. It passes even though we only
974    /// expect a single event, but receive three:
975    ///
976    /// ```
977    /// use tracing_mock::{expect, subscriber};
978    ///
979    /// let (subscriber, handle) = subscriber::mock()
980    ///     .event(expect::event())
981    ///     .run_with_handle();
982    ///
983    /// tracing::subscriber::with_default(subscriber, || {
984    ///     tracing::info!("a");
985    ///     tracing::info!("b");
986    ///     tracing::info!("c");
987    /// });
988    ///
989    /// handle.assert_finished();
990    /// ```
991    ///
992    /// After including `only`, the test will fail:
993    ///
994    /// ```should_panic
995    /// use tracing_mock::{expect, subscriber};
996    ///
997    /// let (subscriber, handle) = subscriber::mock()
998    ///     .event(expect::event())
999    ///     .only()
1000    ///     .run_with_handle();
1001    ///
1002    /// tracing::subscriber::with_default(subscriber, || {
1003    ///     tracing::info!("a");
1004    ///     tracing::info!("b");
1005    ///     tracing::info!("c");
1006    /// });
1007    ///
1008    /// handle.assert_finished();
1009    /// ```
1010    pub fn only(mut self) -> Self {
1011        self.expected.push_back(Expect::Nothing);
1012        self
1013    }
1014
1015    /// Consume the receiver and return an `impl` [`Subscriber`] which can
1016    /// be set as the default subscriber.
1017    ///
1018    /// This function is similar to [`run_with_handle`], but it doesn't
1019    /// return a [`MockHandle`]. This is useful if the desired
1020    /// assertions can be checked externally to the subscriber.
1021    ///
1022    /// # Examples
1023    ///
1024    /// The following test is used within the `tracing`
1025    /// codebase:
1026    ///
1027    /// ```
1028    /// use tracing_mock::subscriber;
1029    ///
1030    /// tracing::subscriber::with_default(subscriber::mock().run(), || {
1031    ///     let foo1 = tracing::span!(tracing::Level::TRACE, "foo");
1032    ///     let foo2 = foo1.clone();
1033    ///     // Two handles that point to the same span are equal.
1034    ///     assert_eq!(foo1, foo2);
1035    /// });
1036    /// ```
1037    ///
1038    /// [`Subscriber`]: tracing::Subscriber
1039    /// [`run_with_handle`]: fn@Self::run_with_handle
1040    pub fn run(self) -> impl Subscriber {
1041        let (subscriber, _) = self.run_with_handle();
1042        subscriber
1043    }
1044
1045    /// Consume the receiver and return an `impl` [`Subscriber`] which can
1046    /// be set as the default subscriber and a [`MockHandle`] which can
1047    /// be used to validate the provided expectations.
1048    ///
1049    /// # Examples
1050    ///
1051    /// ```
1052    /// use tracing_mock::{expect, subscriber};
1053    ///
1054    /// // subscriber and handle are returned from `run_with_handle()`
1055    /// let (subscriber, handle) = subscriber::mock()
1056    ///     .event(expect::event())
1057    ///     .run_with_handle();
1058    ///
1059    /// tracing::subscriber::with_default(subscriber, || {
1060    ///     tracing::info!("a");
1061    /// });
1062    ///
1063    /// handle.assert_finished();
1064    /// ```
1065    ///
1066    /// [`Subscriber`]: tracing::Subscriber
1067    pub fn run_with_handle(self) -> (impl Subscriber, MockHandle) {
1068        let expected = Arc::new(Mutex::new(self.expected));
1069        let handle = MockHandle(expected.clone(), self.name.clone());
1070        let subscriber = Running {
1071            spans: Mutex::new(HashMap::new()),
1072            expected,
1073            current: Mutex::new(Vec::new()),
1074            ids: AtomicUsize::new(1),
1075            filter: self.filter,
1076            max_level: self.max_level,
1077            name: self.name,
1078        };
1079        (subscriber, handle)
1080    }
1081}
1082
1083impl<F> Subscriber for Running<F>
1084where
1085    F: Fn(&Metadata<'_>) -> bool + 'static,
1086{
1087    fn on_register_dispatch(&self, _subscriber: &tracing::Dispatch) {
1088        println!("[{}] on_register_dispatch", self.name);
1089        let mut expected = self.expected.lock().unwrap();
1090        if let Some(Expect::OnRegisterDispatch) = expected.front() {
1091            expected.pop_front();
1092        }
1093    }
1094
1095    fn enabled(&self, meta: &Metadata<'_>) -> bool {
1096        println!("[{}] enabled: {:#?}", self.name, meta);
1097        let enabled = (self.filter)(meta);
1098        println!("[{}] enabled -> {}", self.name, enabled);
1099        enabled
1100    }
1101
1102    fn register_callsite(&self, meta: &'static Metadata<'static>) -> Interest {
1103        println!("[{}] register_callsite: {:#?}", self.name, meta);
1104        if self.enabled(meta) {
1105            Interest::always()
1106        } else {
1107            Interest::never()
1108        }
1109    }
1110    fn max_level_hint(&self) -> Option<LevelFilter> {
1111        self.max_level
1112    }
1113
1114    fn record(&self, id: &Id, values: &span::Record<'_>) {
1115        let spans = self.spans.lock().unwrap();
1116        let mut expected = self.expected.lock().unwrap();
1117        let span = spans
1118            .get(id)
1119            .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id));
1120        println!(
1121            "[{}] record: {}; id={:?}; values={:?};",
1122            self.name, span.name, id, values
1123        );
1124        let was_expected = matches!(expected.front(), Some(Expect::Visit(_, _)));
1125        if was_expected {
1126            if let Expect::Visit(expected_span, mut expected_values) = expected.pop_front().unwrap()
1127            {
1128                if let Some(name) = expected_span.name() {
1129                    assert_eq!(name, span.name);
1130                }
1131                let context = format!("span {}: ", span.name);
1132                let mut checker = expected_values.checker(&context, &self.name);
1133                values.record(&mut checker);
1134                checker.finish();
1135            }
1136        }
1137    }
1138
1139    fn event(&self, event: &Event<'_>) {
1140        let name = event.metadata().name();
1141        println!("[{}] event: {};", self.name, name);
1142        match self.expected.lock().unwrap().pop_front() {
1143            None => {}
1144            Some(Expect::Event(mut expected)) => {
1145                #[cfg(feature = "tracing-subscriber")]
1146                {
1147                    if expected.scope_mut().is_some() {
1148                        unimplemented!(
1149                            "Expected scope for events is not supported with `MockSubscriber`."
1150                        )
1151                    }
1152                }
1153                let event_get_ancestry = || {
1154                    get_ancestry(
1155                        event,
1156                        || self.lookup_current(),
1157                        |span_id| {
1158                            self.spans
1159                                .lock()
1160                                .unwrap()
1161                                .get(span_id)
1162                                .map(|span| span.into())
1163                        },
1164                    )
1165                };
1166                expected.check(event, event_get_ancestry, &self.name);
1167            }
1168            Some(ex) => ex.bad(&self.name, format_args!("observed event {:#?}", event)),
1169        }
1170    }
1171
1172    fn record_follows_from(&self, consequence_id: &Id, cause_id: &Id) {
1173        let spans = self.spans.lock().unwrap();
1174        if let Some(consequence_span) = spans.get(consequence_id) {
1175            if let Some(cause_span) = spans.get(cause_id) {
1176                println!(
1177                    "[{}] record_follows_from: {} (id={:?}) follows {} (id={:?})",
1178                    self.name, consequence_span.name, consequence_id, cause_span.name, cause_id,
1179                );
1180                match self.expected.lock().unwrap().pop_front() {
1181                    None => {}
1182                    Some(Expect::FollowsFrom {
1183                        consequence: ref expected_consequence,
1184                        cause: ref expected_cause,
1185                    }) => {
1186                        if let Some(name) = expected_consequence.name() {
1187                            // TODO(hds): Write proper assertion text.
1188                            assert_eq!(name, consequence_span.name);
1189                        }
1190                        if let Some(name) = expected_cause.name() {
1191                            // TODO(hds): Write proper assertion text.
1192                            assert_eq!(name, cause_span.name);
1193                        }
1194                    }
1195                    Some(ex) => ex.bad(
1196                        &self.name,
1197                        format_args!(
1198                            "consequence {:?} followed cause {:?}",
1199                            consequence_span.name, cause_span.name
1200                        ),
1201                    ),
1202                }
1203            }
1204        };
1205    }
1206
1207    fn new_span(&self, span: &Attributes<'_>) -> Id {
1208        let meta = span.metadata();
1209        let id = self.ids.fetch_add(1, Ordering::SeqCst);
1210        let id = Id::from_u64(id as u64);
1211        println!(
1212            "[{}] new_span: name={:?}; target={:?}; id={:?};",
1213            self.name,
1214            meta.name(),
1215            meta.target(),
1216            id
1217        );
1218        let mut expected = self.expected.lock().unwrap();
1219        let was_expected = matches!(expected.front(), Some(Expect::NewSpan(_)));
1220        let mut spans = self.spans.lock().unwrap();
1221        if was_expected {
1222            if let Expect::NewSpan(mut expected) = expected.pop_front().unwrap() {
1223                if let Some(expected_id) = &expected.span.id {
1224                    expected_id.set(id.into_u64()).unwrap();
1225                }
1226
1227                expected.check(
1228                    span,
1229                    || {
1230                        get_ancestry(
1231                            span,
1232                            || self.lookup_current(),
1233                            |span_id| spans.get(span_id).map(|span| span.into()),
1234                        )
1235                    },
1236                    &self.name,
1237                );
1238            }
1239        }
1240        spans.insert(
1241            id.clone(),
1242            SpanState {
1243                id: id.clone(),
1244                name: meta.name(),
1245                refs: 1,
1246                meta,
1247            },
1248        );
1249        id
1250    }
1251
1252    fn enter(&self, id: &Id) {
1253        let spans = self.spans.lock().unwrap();
1254        if let Some(span) = spans.get(id) {
1255            println!("[{}] enter: {}; id={:?};", self.name, span.name, id);
1256            match self.expected.lock().unwrap().pop_front() {
1257                None => {}
1258                Some(Expect::Enter(ref expected_span)) => {
1259                    expected_span.check(&span.into(), "to enter a span", &self.name);
1260                }
1261                Some(ex) => ex.bad(&self.name, format_args!("entered span {:?}", span.name)),
1262            }
1263        };
1264        self.current.lock().unwrap().push(id.clone());
1265    }
1266
1267    fn exit(&self, id: &Id) {
1268        if std::thread::panicking() {
1269            // `exit()` can be called in `drop` impls, so we must guard against
1270            // double panics.
1271            println!("[{}] exit {:?} while panicking", self.name, id);
1272            return;
1273        }
1274        let spans = self.spans.lock().unwrap();
1275        let span = spans
1276            .get(id)
1277            .unwrap_or_else(|| panic!("[{}] no span for ID {:?}", self.name, id));
1278        println!("[{}] exit: {}; id={:?};", self.name, span.name, id);
1279        match self.expected.lock().unwrap().pop_front() {
1280            None => {}
1281            Some(Expect::Exit(ref expected_span)) => {
1282                expected_span.check(&span.into(), "to exit a span", &self.name);
1283                let curr = self.current.lock().unwrap().pop();
1284                assert_eq!(
1285                    Some(id),
1286                    curr.as_ref(),
1287                    "[{}] exited span {:?}, but the current span was {:?}",
1288                    self.name,
1289                    span.name,
1290                    curr.as_ref().and_then(|id| spans.get(id)).map(|s| s.name)
1291                );
1292            }
1293            Some(ex) => ex.bad(&self.name, format_args!("exited span {:?}", span.name)),
1294        };
1295    }
1296
1297    fn clone_span(&self, id: &Id) -> Id {
1298        let mut spans = self.spans.lock().unwrap();
1299        let mut span = spans.get_mut(id);
1300        match span.as_deref_mut() {
1301            Some(span) => {
1302                println!(
1303                    "[{}] clone_span: {}; id={:?}; refs={:?};",
1304                    self.name, span.name, id, span.refs,
1305                );
1306                span.refs += 1;
1307            }
1308            None => {
1309                println!(
1310                    "[{}] clone_span: id={:?} (not found in span list);",
1311                    self.name, id
1312                );
1313            }
1314        }
1315
1316        let mut expected = self.expected.lock().unwrap();
1317        let was_expected = if let Some(Expect::CloneSpan(ref expected_span)) = expected.front() {
1318            match span {
1319                Some(actual_span) => {
1320                    let actual_span: &_ = actual_span;
1321                    expected_span.check(&actual_span.into(), "to clone a span", &self.name);
1322                }
1323                // Check only by Id
1324                None => expected_span.check(&id.into(), "to clone a span", &self.name),
1325            }
1326            true
1327        } else {
1328            false
1329        };
1330        if was_expected {
1331            expected.pop_front();
1332        }
1333        id.clone()
1334    }
1335
1336    fn drop_span(&self, id: Id) {
1337        let mut is_event = false;
1338        let name = if let Ok(mut spans) = self.spans.try_lock() {
1339            spans.get_mut(&id).map(|span| {
1340                let name = span.name;
1341                if name.contains("event") {
1342                    is_event = true;
1343                }
1344                println!(
1345                    "[{}] drop_span: {}; id={:?}; refs={:?};",
1346                    self.name, name, id, span.refs
1347                );
1348                span.refs -= 1;
1349                name
1350            })
1351        } else {
1352            None
1353        };
1354        if name.is_none() {
1355            println!("[{}] drop_span: id={:?}", self.name, id);
1356        }
1357        if let Ok(mut expected) = self.expected.try_lock() {
1358            let was_expected = match expected.front() {
1359                Some(Expect::DropSpan(ref span)) => {
1360                    // Don't assert if this function was called while panicking,
1361                    // as failing the assertion can cause a double panic.
1362                    if !::std::thread::panicking() {
1363                        assert_eq!(name, span.name());
1364                    }
1365                    true
1366                }
1367                Some(Expect::Event(_)) => {
1368                    if !::std::thread::panicking() {
1369                        assert!(is_event, "[{}] expected an event", self.name);
1370                    }
1371                    true
1372                }
1373                _ => false,
1374            };
1375            if was_expected {
1376                expected.pop_front();
1377            }
1378        }
1379    }
1380
1381    fn current_span(&self) -> tracing_core::span::Current {
1382        let stack = self.current.lock().unwrap();
1383        match stack.last() {
1384            Some(id) => {
1385                let spans = self.spans.lock().unwrap();
1386                let state = spans.get(id).expect("state for current span");
1387                tracing_core::span::Current::new(id.clone(), state.meta)
1388            }
1389            None => tracing_core::span::Current::none(),
1390        }
1391    }
1392}
1393
1394impl<F> Running<F>
1395where
1396    F: Fn(&Metadata<'_>) -> bool,
1397{
1398    fn lookup_current(&self) -> Option<span::Id> {
1399        let stack = self.current.lock().unwrap();
1400        stack.last().cloned()
1401    }
1402}
1403
1404impl MockHandle {
1405    #[cfg(feature = "tracing-subscriber")]
1406    pub(crate) fn new(expected: Arc<Mutex<VecDeque<Expect>>>, name: String) -> Self {
1407        Self(expected, name)
1408    }
1409
1410    /// Checks the expectations which were set on the
1411    /// [`MockSubscriber`].
1412    ///
1413    /// Calling `assert_finished` is usually the final part of a test.
1414    ///
1415    /// # Panics
1416    ///
1417    /// This method will panic if any of the provided expectations are
1418    /// not met.
1419    ///
1420    /// # Examples
1421    ///
1422    /// ```
1423    /// use tracing_mock::{expect, subscriber};
1424    ///
1425    /// let (subscriber, handle) = subscriber::mock()
1426    ///     .event(expect::event())
1427    ///     .run_with_handle();
1428    ///
1429    /// tracing::subscriber::with_default(subscriber, || {
1430    ///     tracing::info!("a");
1431    /// });
1432    ///
1433    /// // Check assertions set on the mock subscriber
1434    /// handle.assert_finished();
1435    /// ```
1436    pub fn assert_finished(&self) {
1437        if let Ok(ref expected) = self.0.lock() {
1438            assert!(
1439                !expected.iter().any(|thing| thing != &Expect::Nothing),
1440                "\n[{}] more notifications expected: {:#?}",
1441                self.1,
1442                **expected
1443            );
1444        }
1445    }
1446}