1 // These tests require the thread-local scoped dispatcher, which only works when
2 // we have a standard library. The behaviour being tested should be the same
3 // with the standard lib disabled.
4 //
5 // The alternative would be for each of these tests to be defined in a separate
6 // file, which is :(
7 #![cfg(feature = "std")]
8 
9 use tracing::{
10     debug, error,
11     field::{debug, display},
12     info,
13     subscriber::with_default,
14     trace, warn, Level,
15 };
16 use tracing_mock::*;
17 
18 macro_rules! event_without_message {
19     ($name:ident: $e:expr) => {
20         #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
21         #[test]
22         fn $name() {
23             let (subscriber, handle) = subscriber::mock()
24                 .event(
25                     expect::event().with_fields(
26                         expect::field("answer")
27                             .with_value(&42)
28                             .and(
29                                 expect::field("to_question")
30                                     .with_value(&"life, the universe, and everything"),
31                             )
32                             .only(),
33                     ),
34                 )
35                 .only()
36                 .run_with_handle();
37 
38             with_default(subscriber, || {
39                 info!(
40                     answer = $e,
41                     to_question = "life, the universe, and everything"
42                 );
43             });
44 
45             handle.assert_finished();
46         }
47     };
48 }
49 
50 event_without_message! {event_without_message: 42}
51 event_without_message! {wrapping_event_without_message: std::num::Wrapping(42)}
52 event_without_message! {nonzeroi32_event_without_message: std::num::NonZeroI32::new(42).unwrap()}
53 // needs API breakage
54 //event_without_message!{nonzerou128_event_without_message: std::num::NonZeroU128::new(42).unwrap()}
55 
56 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
57 #[test]
event_with_message()58 fn event_with_message() {
59     let (subscriber, handle) = subscriber::mock()
60         .event(
61             expect::event().with_fields(expect::field("message").with_value(
62                 &tracing::field::debug(format_args!(
63                     "hello from my tracing::event! yak shaved = {:?}",
64                     true
65                 )),
66             )),
67         )
68         .only()
69         .run_with_handle();
70 
71     with_default(subscriber, || {
72         debug!("hello from my tracing::event! yak shaved = {:?}", true);
73     });
74 
75     handle.assert_finished();
76 }
77 
78 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
79 #[test]
message_without_delims()80 fn message_without_delims() {
81     let (subscriber, handle) = subscriber::mock()
82         .event(
83             expect::event().with_fields(
84                 expect::field("answer")
85                     .with_value(&42)
86                     .and(
87                         expect::field("question").with_value(&"life, the universe, and everything"),
88                     )
89                     .and(field::msg(format_args!(
90                         "hello from my event! tricky? {:?}!",
91                         true
92                     )))
93                     .only(),
94             ),
95         )
96         .only()
97         .run_with_handle();
98 
99     with_default(subscriber, || {
100         let question = "life, the universe, and everything";
101         debug!(answer = 42, question, "hello from {where}! tricky? {:?}!", true, where = "my event");
102     });
103 
104     handle.assert_finished();
105 }
106 
107 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
108 #[test]
string_message_without_delims()109 fn string_message_without_delims() {
110     let (subscriber, handle) = subscriber::mock()
111         .event(
112             expect::event().with_fields(
113                 expect::field("answer")
114                     .with_value(&42)
115                     .and(
116                         expect::field("question").with_value(&"life, the universe, and everything"),
117                     )
118                     .and(field::msg(format_args!("hello from my event")))
119                     .only(),
120             ),
121         )
122         .only()
123         .run_with_handle();
124 
125     with_default(subscriber, || {
126         let question = "life, the universe, and everything";
127         debug!(answer = 42, question, "hello from my event");
128     });
129 
130     handle.assert_finished();
131 }
132 
133 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
134 #[test]
one_with_everything()135 fn one_with_everything() {
136     let (subscriber, handle) = subscriber::mock()
137         .event(
138             expect::event()
139                 .with_fields(
140                     expect::field("message")
141                         .with_value(&tracing::field::debug(format_args!(
142                             "{:#x} make me one with{what:.>20}",
143                             4_277_009_102u64,
144                             what = "everything"
145                         )))
146                         .and(expect::field("foo").with_value(&666))
147                         .and(expect::field("bar").with_value(&false))
148                         .and(expect::field("like_a_butterfly").with_value(&42.0))
149                         .only(),
150                 )
151                 .at_level(Level::ERROR)
152                 .with_target("whatever"),
153         )
154         .only()
155         .run_with_handle();
156 
157     with_default(subscriber, || {
158         tracing::event!(
159             target: "whatever",
160             Level::ERROR,
161             { foo = 666, bar = false, like_a_butterfly = 42.0 },
162              "{:#x} make me one with{what:.>20}", 4_277_009_102u64, what = "everything"
163         );
164     });
165 
166     handle.assert_finished();
167 }
168 
169 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
170 #[test]
moved_field()171 fn moved_field() {
172     let (subscriber, handle) = subscriber::mock()
173         .event(
174             expect::event().with_fields(
175                 expect::field("foo")
176                     .with_value(&display("hello from my event"))
177                     .only(),
178             ),
179         )
180         .only()
181         .run_with_handle();
182     with_default(subscriber, || {
183         let from = "my event";
184         tracing::event!(Level::INFO, foo = display(format!("hello from {}", from)))
185     });
186 
187     handle.assert_finished();
188 }
189 
190 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
191 #[test]
dotted_field_name()192 fn dotted_field_name() {
193     let (subscriber, handle) = subscriber::mock()
194         .event(
195             expect::event().with_fields(
196                 expect::field("foo.bar")
197                     .with_value(&true)
198                     .and(expect::field("foo.baz").with_value(&false))
199                     .only(),
200             ),
201         )
202         .only()
203         .run_with_handle();
204     with_default(subscriber, || {
205         tracing::event!(Level::INFO, foo.bar = true, foo.baz = false);
206     });
207 
208     handle.assert_finished();
209 }
210 
211 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
212 #[test]
borrowed_field()213 fn borrowed_field() {
214     let (subscriber, handle) = subscriber::mock()
215         .event(
216             expect::event().with_fields(
217                 expect::field("foo")
218                     .with_value(&display("hello from my event"))
219                     .only(),
220             ),
221         )
222         .only()
223         .run_with_handle();
224     with_default(subscriber, || {
225         let from = "my event";
226         let mut message = format!("hello from {}", from);
227         tracing::event!(Level::INFO, foo = display(&message));
228         message.push_str(", which happened!");
229     });
230 
231     handle.assert_finished();
232 }
233 
234 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
235 #[test]
236 // If emitting log instrumentation, this gets moved anyway, breaking the test.
237 #[cfg(not(feature = "log"))]
move_field_out_of_struct()238 fn move_field_out_of_struct() {
239     use tracing::field::debug;
240 
241     #[derive(Debug)]
242     struct Position {
243         x: f32,
244         y: f32,
245     }
246 
247     let pos = Position {
248         x: 3.234,
249         y: -1.223,
250     };
251     let (subscriber, handle) = subscriber::mock()
252         .event(
253             expect::event().with_fields(
254                 expect::field("x")
255                     .with_value(&debug(3.234))
256                     .and(expect::field("y").with_value(&debug(-1.223)))
257                     .only(),
258             ),
259         )
260         .event(expect::event().with_fields(expect::field("position").with_value(&debug(&pos))))
261         .only()
262         .run_with_handle();
263 
264     with_default(subscriber, || {
265         let pos = Position {
266             x: 3.234,
267             y: -1.223,
268         };
269         debug!(x = debug(pos.x), y = debug(pos.y));
270         debug!(target: "app_events", { position = debug(pos) }, "New position");
271     });
272     handle.assert_finished();
273 }
274 
275 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
276 #[test]
display_shorthand()277 fn display_shorthand() {
278     let (subscriber, handle) = subscriber::mock()
279         .event(
280             expect::event().with_fields(
281                 expect::field("my_field")
282                     .with_value(&display("hello world"))
283                     .only(),
284             ),
285         )
286         .only()
287         .run_with_handle();
288     with_default(subscriber, || {
289         tracing::event!(Level::TRACE, my_field = %"hello world");
290     });
291 
292     handle.assert_finished();
293 }
294 
295 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
296 #[test]
debug_shorthand()297 fn debug_shorthand() {
298     let (subscriber, handle) = subscriber::mock()
299         .event(
300             expect::event().with_fields(
301                 expect::field("my_field")
302                     .with_value(&debug("hello world"))
303                     .only(),
304             ),
305         )
306         .only()
307         .run_with_handle();
308     with_default(subscriber, || {
309         tracing::event!(Level::TRACE, my_field = ?"hello world");
310     });
311 
312     handle.assert_finished();
313 }
314 
315 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
316 #[test]
both_shorthands()317 fn both_shorthands() {
318     let (subscriber, handle) = subscriber::mock()
319         .event(
320             expect::event().with_fields(
321                 expect::field("display_field")
322                     .with_value(&display("hello world"))
323                     .and(expect::field("debug_field").with_value(&debug("hello world")))
324                     .only(),
325             ),
326         )
327         .only()
328         .run_with_handle();
329     with_default(subscriber, || {
330         tracing::event!(Level::TRACE, display_field = %"hello world", debug_field = ?"hello world");
331     });
332 
333     handle.assert_finished();
334 }
335 
336 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
337 #[test]
explicit_child()338 fn explicit_child() {
339     let (subscriber, handle) = subscriber::mock()
340         .new_span(expect::span().named("foo"))
341         .event(expect::event().with_explicit_parent(Some("foo")))
342         .only()
343         .run_with_handle();
344 
345     with_default(subscriber, || {
346         let foo = tracing::span!(Level::TRACE, "foo");
347         tracing::event!(parent: foo.id(), Level::TRACE, "bar");
348     });
349 
350     handle.assert_finished();
351 }
352 
353 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
354 #[test]
explicit_child_at_levels()355 fn explicit_child_at_levels() {
356     let (subscriber, handle) = subscriber::mock()
357         .new_span(expect::span().named("foo"))
358         .event(expect::event().with_explicit_parent(Some("foo")))
359         .event(expect::event().with_explicit_parent(Some("foo")))
360         .event(expect::event().with_explicit_parent(Some("foo")))
361         .event(expect::event().with_explicit_parent(Some("foo")))
362         .event(expect::event().with_explicit_parent(Some("foo")))
363         .only()
364         .run_with_handle();
365 
366     with_default(subscriber, || {
367         let foo = tracing::span!(Level::TRACE, "foo");
368         trace!(parent: foo.id(), "a");
369         debug!(parent: foo.id(), "b");
370         info!(parent: foo.id(), "c");
371         warn!(parent: foo.id(), "d");
372         error!(parent: foo.id(), "e");
373     });
374 
375     handle.assert_finished();
376 }
377 
378 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
379 #[test]
option_values()380 fn option_values() {
381     let (subscriber, handle) = subscriber::mock()
382         .event(
383             expect::event().with_fields(
384                 expect::field("some_str")
385                     .with_value(&"yes")
386                     .and(expect::field("some_bool").with_value(&true))
387                     .and(expect::field("some_u64").with_value(&42_u64))
388                     .only(),
389             ),
390         )
391         .only()
392         .run_with_handle();
393 
394     with_default(subscriber, || {
395         let some_str = Some("yes");
396         let none_str: Option<&'static str> = None;
397         let some_bool = Some(true);
398         let none_bool: Option<bool> = None;
399         let some_u64 = Some(42_u64);
400         let none_u64: Option<u64> = None;
401         trace!(
402             some_str = some_str,
403             none_str = none_str,
404             some_bool = some_bool,
405             none_bool = none_bool,
406             some_u64 = some_u64,
407             none_u64 = none_u64
408         );
409     });
410 
411     handle.assert_finished();
412 }
413 
414 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
415 #[test]
option_ref_values()416 fn option_ref_values() {
417     let (subscriber, handle) = subscriber::mock()
418         .event(
419             expect::event().with_fields(
420                 expect::field("some_str")
421                     .with_value(&"yes")
422                     .and(expect::field("some_bool").with_value(&true))
423                     .and(expect::field("some_u64").with_value(&42_u64))
424                     .only(),
425             ),
426         )
427         .only()
428         .run_with_handle();
429 
430     with_default(subscriber, || {
431         let some_str = &Some("yes");
432         let none_str: &Option<&'static str> = &None;
433         let some_bool = &Some(true);
434         let none_bool: &Option<bool> = &None;
435         let some_u64 = &Some(42_u64);
436         let none_u64: &Option<u64> = &None;
437         trace!(
438             some_str = some_str,
439             none_str = none_str,
440             some_bool = some_bool,
441             none_bool = none_bool,
442             some_u64 = some_u64,
443             none_u64 = none_u64
444         );
445     });
446 
447     handle.assert_finished();
448 }
449 
450 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
451 #[test]
option_ref_mut_values()452 fn option_ref_mut_values() {
453     let (subscriber, handle) = subscriber::mock()
454         .event(
455             expect::event().with_fields(
456                 expect::field("some_str")
457                     .with_value(&"yes")
458                     .and(expect::field("some_bool").with_value(&true))
459                     .and(expect::field("some_u64").with_value(&42_u64))
460                     .only(),
461             ),
462         )
463         .only()
464         .run_with_handle();
465 
466     with_default(subscriber, || {
467         let some_str = &mut Some("yes");
468         let none_str: &mut Option<&'static str> = &mut None;
469         let some_bool = &mut Some(true);
470         let none_bool: &mut Option<bool> = &mut None;
471         let some_u64 = &mut Some(42_u64);
472         let none_u64: &mut Option<u64> = &mut None;
473         trace!(
474             some_str = some_str,
475             none_str = none_str,
476             some_bool = some_bool,
477             none_bool = none_bool,
478             some_u64 = some_u64,
479             none_u64 = none_u64
480         );
481     });
482 
483     handle.assert_finished();
484 }
485 
486 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
487 #[test]
string_field()488 fn string_field() {
489     let (subscriber, handle) = subscriber::mock()
490         .event(expect::event().with_fields(expect::field("my_string").with_value(&"hello").only()))
491         .event(
492             expect::event().with_fields(
493                 expect::field("my_string")
494                     .with_value(&"hello world!")
495                     .only(),
496             ),
497         )
498         .only()
499         .run_with_handle();
500     with_default(subscriber, || {
501         let mut my_string = String::from("hello");
502 
503         tracing::event!(Level::INFO, my_string);
504 
505         // the string is not moved by using it as a field!
506         my_string.push_str(" world!");
507 
508         tracing::event!(Level::INFO, my_string);
509     });
510 
511     handle.assert_finished();
512 }
513 
514 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
515 #[test]
constant_field_name()516 fn constant_field_name() {
517     let expect_event = || {
518         expect::event().with_fields(
519             expect::field("foo")
520                 .with_value(&"bar")
521                 .and(expect::field("constant string").with_value(&"also works"))
522                 .and(expect::field("foo.bar").with_value(&"baz"))
523                 .and(expect::field("message").with_value(&debug(format_args!("quux"))))
524                 .only(),
525         )
526     };
527     let (subscriber, handle) = subscriber::mock()
528         .event(expect_event())
529         .event(expect_event())
530         .only()
531         .run_with_handle();
532 
533     with_default(subscriber, || {
534         const FOO: &str = "foo";
535         tracing::event!(
536             Level::INFO,
537             { std::convert::identity(FOO) } = "bar",
538             { "constant string" } = "also works",
539             foo.bar = "baz",
540             "quux"
541         );
542         tracing::event!(
543             Level::INFO,
544             {
545                 { std::convert::identity(FOO) } = "bar",
546                 { "constant string" } = "also works",
547                 foo.bar = "baz",
548             },
549             "quux"
550         );
551     });
552 
553     handle.assert_finished();
554 }
555