1use tracing::{subscriber::with_default, Id, Level, Span};
2use tracing_attributes::instrument;
3use tracing_mock::*;
4
5#[instrument(follows_from = causes, skip(causes))]
6fn with_follows_from_sync(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
7
8#[instrument(follows_from = causes, skip(causes))]
9async fn with_follows_from_async(causes: impl IntoIterator<Item = impl Into<Option<Id>>>) {}
10
11#[instrument(follows_from = [&Span::current()])]
12fn follows_from_current() {}
13
14#[test]
15fn follows_from_sync_test() {
16 let cause_a = expect::span().named("cause_a");
17 let cause_b = expect::span().named("cause_b");
18 let cause_c = expect::span().named("cause_c");
19 let consequence = expect::span().named("with_follows_from_sync");
20
21 let (subscriber, handle) = subscriber::mock()
22 .new_span(cause_a.clone())
23 .new_span(cause_b.clone())
24 .new_span(cause_c.clone())
25 .new_span(consequence.clone())
26 .follows_from(consequence.clone(), cause_a)
27 .follows_from(consequence.clone(), cause_b)
28 .follows_from(consequence.clone(), cause_c)
29 .enter(consequence.clone())
30 .exit(consequence)
31 .only()
32 .run_with_handle();
33
34 with_default(subscriber, || {
35 let cause_a = tracing::span!(Level::TRACE, "cause_a");
36 let cause_b = tracing::span!(Level::TRACE, "cause_b");
37 let cause_c = tracing::span!(Level::TRACE, "cause_c");
38
39 with_follows_from_sync(&[cause_a, cause_b, cause_c])
40 });
41
42 handle.assert_finished();
43}
44
45#[test]
46fn follows_from_async_test() {
47 let cause_a = expect::span().named("cause_a");
48 let cause_b = expect::span().named("cause_b");
49 let cause_c = expect::span().named("cause_c");
50 let consequence = expect::span().named("with_follows_from_async");
51
52 let (subscriber, handle) = subscriber::mock()
53 .new_span(cause_a.clone())
54 .new_span(cause_b.clone())
55 .new_span(cause_c.clone())
56 .new_span(consequence.clone())
57 .follows_from(consequence.clone(), cause_a)
58 .follows_from(consequence.clone(), cause_b)
59 .follows_from(consequence.clone(), cause_c)
60 .enter(consequence.clone())
61 .exit(consequence.clone())
62 .enter(consequence.clone())
63 .exit(consequence)
64 .only()
65 .run_with_handle();
66
67 with_default(subscriber, || {
68 block_on_future(async {
69 let cause_a = tracing::span!(Level::TRACE, "cause_a");
70 let cause_b = tracing::span!(Level::TRACE, "cause_b");
71 let cause_c = tracing::span!(Level::TRACE, "cause_c");
72
73 with_follows_from_async(&[cause_a, cause_b, cause_c]).await
74 })
75 });
76
77 handle.assert_finished();
78}
79
80#[test]
81fn follows_from_current_test() {
82 let cause = expect::span().named("cause");
83 let consequence = expect::span().named("follows_from_current");
84
85 let (subscriber, handle) = subscriber::mock()
86 .new_span(cause.clone())
87 .enter(cause.clone())
88 .new_span(consequence.clone())
89 .follows_from(consequence.clone(), cause.clone())
90 .enter(consequence.clone())
91 .exit(consequence)
92 .exit(cause)
93 .only()
94 .run_with_handle();
95
96 with_default(subscriber, || {
97 tracing::span!(Level::TRACE, "cause").in_scope(follows_from_current)
98 });
99
100 handle.assert_finished();
101}
102