1use tracing::subscriber::with_default;
2use tracing_attributes::instrument;
3use tracing_mock::{expect, span::NewSpan, subscriber};
4
5#[instrument(fields(foo = "bar", dsa = true, num = 1))]
6fn fn_no_param() {}
7
8#[instrument(fields(foo = "bar"))]
9fn fn_param(param: u32) {}
10
11#[instrument(fields(foo = "bar", empty))]
12fn fn_empty_field() {}
13
14#[instrument(fields(len = s.len()))]
15fn fn_expr_field(s: &str) {}
16
17#[instrument(fields(s.len = s.len(), s.is_empty = s.is_empty()))]
18fn fn_two_expr_fields(s: &str) {
19 let _ = s;
20}
21
22#[instrument(fields(%s, s.len = s.len()))]
23fn fn_clashy_expr_field(s: &str) {
24 let _ = s;
25}
26
27#[instrument(fields(s = "s"))]
28fn fn_clashy_expr_field2(s: &str) {
29 let _ = s;
30}
31
32#[instrument(fields(s = &s))]
33fn fn_string(s: String) {
34 let _ = s;
35}
36
37#[derive(Debug)]
38struct HasField {
39 my_field: &'static str,
40}
41
42impl HasField {
43 #[instrument(fields(my_field = self.my_field), skip(self))]
44 fn self_expr_field(&self) {}
45}
46
47#[test]
48fn fields() {
49 let span = expect::span().with_field(
50 expect::field("foo")
51 .with_value(&"bar")
52 .and(expect::field("dsa").with_value(&true))
53 .and(expect::field("num").with_value(&1))
54 .only(),
55 );
56 run_test(span, || {
57 fn_no_param();
58 });
59}
60
61#[test]
62fn expr_field() {
63 let span = expect::span().with_field(
64 expect::field("s")
65 .with_value(&"hello world")
66 .and(expect::field("len").with_value(&"hello world".len()))
67 .only(),
68 );
69 run_test(span, || {
70 fn_expr_field("hello world");
71 });
72}
73
74#[test]
75fn two_expr_fields() {
76 let span = expect::span().with_field(
77 expect::field("s")
78 .with_value(&"hello world")
79 .and(expect::field("s.len").with_value(&"hello world".len()))
80 .and(expect::field("s.is_empty").with_value(&false))
81 .only(),
82 );
83 run_test(span, || {
84 fn_two_expr_fields("hello world");
85 });
86}
87
88#[test]
89fn clashy_expr_field() {
90 let span = expect::span().with_field(
91 // Overriding the `s` field should record `s` as a `Display` value,
92 // rather than as a `Debug` value.
93 expect::field("s")
94 .with_value(&tracing::field::display("hello world"))
95 .and(expect::field("s.len").with_value(&"hello world".len()))
96 .only(),
97 );
98 run_test(span, || {
99 fn_clashy_expr_field("hello world");
100 });
101
102 let span = expect::span().with_field(expect::field("s").with_value(&"s").only());
103 run_test(span, || {
104 fn_clashy_expr_field2("hello world");
105 });
106}
107
108#[test]
109fn self_expr_field() {
110 let span =
111 expect::span().with_field(expect::field("my_field").with_value(&"hello world").only());
112 run_test(span, || {
113 let has_field = HasField {
114 my_field: "hello world",
115 };
116 has_field.self_expr_field();
117 });
118}
119
120#[test]
121fn parameters_with_fields() {
122 let span = expect::span().with_field(
123 expect::field("foo")
124 .with_value(&"bar")
125 .and(expect::field("param").with_value(&1u32))
126 .only(),
127 );
128 run_test(span, || {
129 fn_param(1);
130 });
131}
132
133#[test]
134fn empty_field() {
135 let span = expect::span().with_field(expect::field("foo").with_value(&"bar").only());
136 run_test(span, || {
137 fn_empty_field();
138 });
139}
140
141#[test]
142fn string_field() {
143 let span = expect::span().with_field(expect::field("s").with_value(&"hello world").only());
144 run_test(span, || {
145 fn_string(String::from("hello world"));
146 });
147}
148
149fn run_test<F: FnOnce() -> T, T>(span: NewSpan, fun: F) {
150 let (subscriber, handle) = subscriber::mock()
151 .new_span(span)
152 .enter(expect::span())
153 .exit(expect::span())
154 .only()
155 .run_with_handle();
156
157 with_default(subscriber, fun);
158 handle.assert_finished();
159}
160