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 #![cfg(feature = "std")]
5
6 use std::thread;
7
8 use tracing::{
9 error_span,
10 field::{debug, display},
11 subscriber::with_default,
12 Level, Span,
13 };
14 use tracing_mock::*;
15
16 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
17 #[test]
handles_to_the_same_span_are_equal()18 fn handles_to_the_same_span_are_equal() {
19 // Create a mock subscriber that will return `true` on calls to
20 // `Subscriber::enabled`, so that the spans will be constructed. We
21 // won't enter any spans in this test, so the subscriber won't actually
22 // expect to see any spans.
23 with_default(subscriber::mock().run(), || {
24 let foo1 = tracing::span!(Level::TRACE, "foo");
25
26 // The purpose of this test is to assert that two clones of the same
27 // span are equal, so the clone here is kind of the whole point :)
28 #[allow(clippy::redundant_clone)]
29 let foo2 = foo1.clone();
30
31 // Two handles that point to the same span are equal.
32 assert_eq!(foo1, foo2);
33 });
34 }
35
36 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
37 #[test]
handles_to_different_spans_are_not_equal()38 fn handles_to_different_spans_are_not_equal() {
39 with_default(subscriber::mock().run(), || {
40 // Even though these spans have the same name and fields, they will have
41 // differing metadata, since they were created on different lines.
42 let foo1 = tracing::span!(Level::TRACE, "foo", bar = 1u64, baz = false);
43 let foo2 = tracing::span!(Level::TRACE, "foo", bar = 1u64, baz = false);
44
45 assert_ne!(foo1, foo2);
46 });
47 }
48
49 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
50 #[test]
handles_to_different_spans_with_the_same_metadata_are_not_equal()51 fn handles_to_different_spans_with_the_same_metadata_are_not_equal() {
52 // Every time time this function is called, it will return a _new
53 // instance_ of a span with the same metadata, name, and fields.
54 fn make_span() -> Span {
55 tracing::span!(Level::TRACE, "foo", bar = 1u64, baz = false)
56 }
57
58 with_default(subscriber::mock().run(), || {
59 let foo1 = make_span();
60 let foo2 = make_span();
61
62 assert_ne!(foo1, foo2);
63 // assert_ne!(foo1.data(), foo2.data());
64 });
65 }
66
67 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
68 #[test]
spans_always_go_to_the_subscriber_that_tagged_them()69 fn spans_always_go_to_the_subscriber_that_tagged_them() {
70 let subscriber1 = subscriber::mock()
71 .enter(expect::span().named("foo"))
72 .exit(expect::span().named("foo"))
73 .enter(expect::span().named("foo"))
74 .exit(expect::span().named("foo"))
75 .drop_span(expect::span().named("foo"))
76 .only()
77 .run();
78 let subscriber2 = subscriber::mock().run();
79
80 let foo = with_default(subscriber1, || {
81 let foo = tracing::span!(Level::TRACE, "foo");
82 foo.in_scope(|| {});
83 foo
84 });
85 // Even though we enter subscriber 2's context, the subscriber that
86 // tagged the span should see the enter/exit.
87 with_default(subscriber2, move || foo.in_scope(|| {}));
88 }
89
90 // This gets exempt from testing in wasm because of: `thread::spawn` which is
91 // not yet possible to do in WASM. There is work going on see:
92 // <https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html>
93 //
94 // But for now since it's not possible we don't need to test for it :)
95 #[test]
spans_always_go_to_the_subscriber_that_tagged_them_even_across_threads()96 fn spans_always_go_to_the_subscriber_that_tagged_them_even_across_threads() {
97 let subscriber1 = subscriber::mock()
98 .enter(expect::span().named("foo"))
99 .exit(expect::span().named("foo"))
100 .enter(expect::span().named("foo"))
101 .exit(expect::span().named("foo"))
102 .drop_span(expect::span().named("foo"))
103 .only()
104 .run();
105 let foo = with_default(subscriber1, || {
106 let foo = tracing::span!(Level::TRACE, "foo");
107 foo.in_scope(|| {});
108 foo
109 });
110
111 // Even though we enter subscriber 2's context, the subscriber that
112 // tagged the span should see the enter/exit.
113 thread::spawn(move || {
114 with_default(subscriber::mock().run(), || {
115 foo.in_scope(|| {});
116 })
117 })
118 .join()
119 .unwrap();
120 }
121
122 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
123 #[test]
dropping_a_span_calls_drop_span()124 fn dropping_a_span_calls_drop_span() {
125 let (subscriber, handle) = subscriber::mock()
126 .enter(expect::span().named("foo"))
127 .exit(expect::span().named("foo"))
128 .drop_span(expect::span().named("foo"))
129 .only()
130 .run_with_handle();
131 with_default(subscriber, || {
132 let span = tracing::span!(Level::TRACE, "foo");
133 span.in_scope(|| {});
134 drop(span);
135 });
136
137 handle.assert_finished();
138 }
139
140 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
141 #[test]
span_closes_after_event()142 fn span_closes_after_event() {
143 let (subscriber, handle) = subscriber::mock()
144 .enter(expect::span().named("foo"))
145 .event(expect::event())
146 .exit(expect::span().named("foo"))
147 .drop_span(expect::span().named("foo"))
148 .only()
149 .run_with_handle();
150 with_default(subscriber, || {
151 tracing::span!(Level::TRACE, "foo").in_scope(|| {
152 tracing::event!(Level::DEBUG, {}, "my tracing::event!");
153 });
154 });
155
156 handle.assert_finished();
157 }
158
159 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
160 #[test]
new_span_after_event()161 fn new_span_after_event() {
162 let (subscriber, handle) = subscriber::mock()
163 .enter(expect::span().named("foo"))
164 .event(expect::event())
165 .exit(expect::span().named("foo"))
166 .drop_span(expect::span().named("foo"))
167 .enter(expect::span().named("bar"))
168 .exit(expect::span().named("bar"))
169 .drop_span(expect::span().named("bar"))
170 .only()
171 .run_with_handle();
172 with_default(subscriber, || {
173 tracing::span!(Level::TRACE, "foo").in_scope(|| {
174 tracing::event!(Level::DEBUG, {}, "my tracing::event!");
175 });
176 tracing::span!(Level::TRACE, "bar").in_scope(|| {});
177 });
178
179 handle.assert_finished();
180 }
181
182 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
183 #[test]
event_outside_of_span()184 fn event_outside_of_span() {
185 let (subscriber, handle) = subscriber::mock()
186 .event(expect::event())
187 .enter(expect::span().named("foo"))
188 .exit(expect::span().named("foo"))
189 .drop_span(expect::span().named("foo"))
190 .only()
191 .run_with_handle();
192 with_default(subscriber, || {
193 tracing::debug!("my tracing::event!");
194 tracing::span!(Level::TRACE, "foo").in_scope(|| {});
195 });
196
197 handle.assert_finished();
198 }
199
200 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
201 #[test]
cloning_a_span_calls_clone_span()202 fn cloning_a_span_calls_clone_span() {
203 let (subscriber, handle) = subscriber::mock()
204 .clone_span(expect::span().named("foo"))
205 .run_with_handle();
206 with_default(subscriber, || {
207 let span = tracing::span!(Level::TRACE, "foo");
208 // Allow the "redundant" `.clone` since it is used to call into the `.clone_span` hook.
209 #[allow(clippy::redundant_clone)]
210 let _span2 = span.clone();
211 });
212
213 handle.assert_finished();
214 }
215
216 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
217 #[test]
drop_span_when_exiting_dispatchers_context()218 fn drop_span_when_exiting_dispatchers_context() {
219 let (subscriber, handle) = subscriber::mock()
220 .clone_span(expect::span().named("foo"))
221 .drop_span(expect::span().named("foo"))
222 .drop_span(expect::span().named("foo"))
223 .run_with_handle();
224 with_default(subscriber, || {
225 let span = tracing::span!(Level::TRACE, "foo");
226 let _span2 = span.clone();
227 drop(span);
228 });
229
230 handle.assert_finished();
231 }
232
233 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
234 #[test]
clone_and_drop_span_always_go_to_the_subscriber_that_tagged_the_span()235 fn clone_and_drop_span_always_go_to_the_subscriber_that_tagged_the_span() {
236 let (subscriber1, handle1) = subscriber::mock()
237 .enter(expect::span().named("foo"))
238 .exit(expect::span().named("foo"))
239 .clone_span(expect::span().named("foo"))
240 .enter(expect::span().named("foo"))
241 .exit(expect::span().named("foo"))
242 .drop_span(expect::span().named("foo"))
243 .drop_span(expect::span().named("foo"))
244 .run_with_handle();
245 let subscriber2 = subscriber::mock().only().run();
246
247 let foo = with_default(subscriber1, || {
248 let foo = tracing::span!(Level::TRACE, "foo");
249 foo.in_scope(|| {});
250 foo
251 });
252 // Even though we enter subscriber 2's context, the subscriber that
253 // tagged the span should see the enter/exit.
254 with_default(subscriber2, move || {
255 let foo2 = foo.clone();
256 foo.in_scope(|| {});
257 drop(foo);
258 drop(foo2);
259 });
260
261 handle1.assert_finished();
262 }
263
264 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
265 #[test]
span_closes_when_exited()266 fn span_closes_when_exited() {
267 let (subscriber, handle) = subscriber::mock()
268 .enter(expect::span().named("foo"))
269 .exit(expect::span().named("foo"))
270 .drop_span(expect::span().named("foo"))
271 .only()
272 .run_with_handle();
273 with_default(subscriber, || {
274 let foo = tracing::span!(Level::TRACE, "foo");
275
276 foo.in_scope(|| {});
277
278 drop(foo);
279 });
280
281 handle.assert_finished();
282 }
283
284 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
285 #[test]
enter()286 fn enter() {
287 let (subscriber, handle) = subscriber::mock()
288 .enter(expect::span().named("foo"))
289 .event(expect::event())
290 .exit(expect::span().named("foo"))
291 .drop_span(expect::span().named("foo"))
292 .only()
293 .run_with_handle();
294 with_default(subscriber, || {
295 let foo = tracing::span!(Level::TRACE, "foo");
296 let _enter = foo.enter();
297 tracing::debug!("dropping guard...");
298 });
299
300 handle.assert_finished();
301 }
302
303 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
304 #[test]
entered()305 fn entered() {
306 let (subscriber, handle) = subscriber::mock()
307 .enter(expect::span().named("foo"))
308 .event(expect::event())
309 .exit(expect::span().named("foo"))
310 .drop_span(expect::span().named("foo"))
311 .only()
312 .run_with_handle();
313 with_default(subscriber, || {
314 let _span = tracing::span!(Level::TRACE, "foo").entered();
315 tracing::debug!("dropping guard...");
316 });
317
318 handle.assert_finished();
319 }
320
321 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
322 #[test]
entered_api()323 fn entered_api() {
324 let (subscriber, handle) = subscriber::mock()
325 .enter(expect::span().named("foo"))
326 .event(expect::event())
327 .exit(expect::span().named("foo"))
328 .drop_span(expect::span().named("foo"))
329 .only()
330 .run_with_handle();
331 with_default(subscriber, || {
332 let span = tracing::span!(Level::TRACE, "foo").entered();
333 let _derefs_to_span = span.id();
334 tracing::debug!("exiting span...");
335 let _: Span = span.exit();
336 });
337
338 handle.assert_finished();
339 }
340
341 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
342 #[test]
moved_field()343 fn moved_field() {
344 let (subscriber, handle) = subscriber::mock()
345 .new_span(
346 expect::span().named("foo").with_fields(
347 expect::field("bar")
348 .with_value(&display("hello from my span"))
349 .only(),
350 ),
351 )
352 .enter(expect::span().named("foo"))
353 .exit(expect::span().named("foo"))
354 .drop_span(expect::span().named("foo"))
355 .only()
356 .run_with_handle();
357 with_default(subscriber, || {
358 let from = "my span";
359 let span = tracing::span!(
360 Level::TRACE,
361 "foo",
362 bar = display(format!("hello from {}", from))
363 );
364 span.in_scope(|| {});
365 });
366
367 handle.assert_finished();
368 }
369
370 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
371 #[test]
dotted_field_name()372 fn dotted_field_name() {
373 let (subscriber, handle) = subscriber::mock()
374 .new_span(
375 expect::span()
376 .named("foo")
377 .with_fields(expect::field("fields.bar").with_value(&true).only()),
378 )
379 .only()
380 .run_with_handle();
381 with_default(subscriber, || {
382 tracing::span!(Level::TRACE, "foo", fields.bar = true);
383 });
384
385 handle.assert_finished();
386 }
387
388 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
389 #[test]
borrowed_field()390 fn borrowed_field() {
391 let (subscriber, handle) = subscriber::mock()
392 .new_span(
393 expect::span().named("foo").with_fields(
394 expect::field("bar")
395 .with_value(&display("hello from my span"))
396 .only(),
397 ),
398 )
399 .enter(expect::span().named("foo"))
400 .exit(expect::span().named("foo"))
401 .drop_span(expect::span().named("foo"))
402 .only()
403 .run_with_handle();
404
405 with_default(subscriber, || {
406 let from = "my span";
407 let mut message = format!("hello from {}", from);
408 let span = tracing::span!(Level::TRACE, "foo", bar = display(&message));
409 span.in_scope(|| {
410 message.insert_str(10, " inside");
411 });
412 });
413
414 handle.assert_finished();
415 }
416
417 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
418 #[test]
419 // If emitting log instrumentation, this gets moved anyway, breaking the test.
420 #[cfg(not(feature = "log"))]
move_field_out_of_struct()421 fn move_field_out_of_struct() {
422 use tracing::field::debug;
423
424 #[derive(Debug)]
425 struct Position {
426 x: f32,
427 y: f32,
428 }
429
430 let pos = Position {
431 x: 3.234,
432 y: -1.223,
433 };
434 let (subscriber, handle) = subscriber::mock()
435 .new_span(
436 expect::span().named("foo").with_fields(
437 expect::field("x")
438 .with_value(&debug(3.234))
439 .and(expect::field("y").with_value(&debug(-1.223)))
440 .only(),
441 ),
442 )
443 .new_span(
444 expect::span()
445 .named("bar")
446 .with_fields(expect::field("position").with_value(&debug(&pos)).only()),
447 )
448 .run_with_handle();
449
450 with_default(subscriber, || {
451 let pos = Position {
452 x: 3.234,
453 y: -1.223,
454 };
455 let foo = tracing::span!(Level::TRACE, "foo", x = debug(pos.x), y = debug(pos.y));
456 let bar = tracing::span!(Level::TRACE, "bar", position = debug(pos));
457 foo.in_scope(|| {});
458 bar.in_scope(|| {});
459 });
460
461 handle.assert_finished();
462 }
463
464 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
465 #[test]
float_values()466 fn float_values() {
467 let (subscriber, handle) = subscriber::mock()
468 .new_span(
469 expect::span().named("foo").with_fields(
470 expect::field("x")
471 .with_value(&3.234)
472 .and(expect::field("y").with_value(&-1.223))
473 .only(),
474 ),
475 )
476 .run_with_handle();
477
478 with_default(subscriber, || {
479 let foo = tracing::span!(Level::TRACE, "foo", x = 3.234, y = -1.223);
480 foo.in_scope(|| {});
481 });
482
483 handle.assert_finished();
484 }
485
486 // TODO(#1138): determine a new syntax for uninitialized span fields, and
487 // re-enable these.
488 /*
489 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
490 #[test]
491 fn add_field_after_new_span() {
492 let (subscriber, handle) = subscriber::mock()
493 .new_span(
494 expect::span()
495 .named("foo")
496 .with_fields(expect::field("bar").with_value(&5)
497 .and(expect::field("baz").with_value).only()),
498 )
499 .record(
500 expect::span().named("foo"),
501 field::expect("baz").with_value(&true).only(),
502 )
503 .enter(expect::span().named("foo"))
504 .exit(expect::span().named("foo"))
505 .drop_span(expect::span().named("foo"))
506 .only()
507 .run_with_handle();
508
509 with_default(subscriber, || {
510 let span = tracing::span!(Level::TRACE, "foo", bar = 5, baz = false);
511 span.record("baz", &true);
512 span.in_scope(|| {})
513 });
514
515 handle.assert_finished();
516 }
517
518 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
519 #[test]
520 fn add_fields_only_after_new_span() {
521 let (subscriber, handle) = subscriber::mock()
522 .new_span(expect::span().named("foo"))
523 .record(
524 expect::span().named("foo"),
525 field::expect("bar").with_value(&5).only(),
526 )
527 .record(
528 expect::span().named("foo"),
529 field::expect("baz").with_value(&true).only(),
530 )
531 .enter(expect::span().named("foo"))
532 .exit(expect::span().named("foo"))
533 .drop_span(expect::span().named("foo"))
534 .only()
535 .run_with_handle();
536
537 with_default(subscriber, || {
538 let span = tracing::span!(Level::TRACE, "foo", bar = _, baz = _);
539 span.record("bar", &5);
540 span.record("baz", &true);
541 span.in_scope(|| {})
542 });
543
544 handle.assert_finished();
545 }
546 */
547
548 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
549 #[test]
record_new_value_for_field()550 fn record_new_value_for_field() {
551 let (subscriber, handle) = subscriber::mock()
552 .new_span(
553 expect::span().named("foo").with_fields(
554 expect::field("bar")
555 .with_value(&5)
556 .and(expect::field("baz").with_value(&false))
557 .only(),
558 ),
559 )
560 .record(
561 expect::span().named("foo"),
562 expect::field("baz").with_value(&true).only(),
563 )
564 .enter(expect::span().named("foo"))
565 .exit(expect::span().named("foo"))
566 .drop_span(expect::span().named("foo"))
567 .only()
568 .run_with_handle();
569
570 with_default(subscriber, || {
571 let span = tracing::span!(Level::TRACE, "foo", bar = 5, baz = false);
572 span.record("baz", true);
573 span.in_scope(|| {})
574 });
575
576 handle.assert_finished();
577 }
578
579 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
580 #[test]
record_new_values_for_fields()581 fn record_new_values_for_fields() {
582 let (subscriber, handle) = subscriber::mock()
583 .new_span(
584 expect::span().named("foo").with_fields(
585 expect::field("bar")
586 .with_value(&4)
587 .and(expect::field("baz").with_value(&false))
588 .only(),
589 ),
590 )
591 .record(
592 expect::span().named("foo"),
593 expect::field("bar").with_value(&5).only(),
594 )
595 .record(
596 expect::span().named("foo"),
597 expect::field("baz").with_value(&true).only(),
598 )
599 .enter(expect::span().named("foo"))
600 .exit(expect::span().named("foo"))
601 .drop_span(expect::span().named("foo"))
602 .only()
603 .run_with_handle();
604
605 with_default(subscriber, || {
606 let span = tracing::span!(Level::TRACE, "foo", bar = 4, baz = false);
607 span.record("bar", 5);
608 span.record("baz", true);
609 span.in_scope(|| {})
610 });
611
612 handle.assert_finished();
613 }
614
615 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
616 #[test]
new_span_with_target_and_log_level()617 fn new_span_with_target_and_log_level() {
618 let (subscriber, handle) = subscriber::mock()
619 .new_span(
620 expect::span()
621 .named("foo")
622 .with_target("app_span")
623 .at_level(Level::DEBUG),
624 )
625 .only()
626 .run_with_handle();
627
628 with_default(subscriber, || {
629 tracing::span!(target: "app_span", Level::DEBUG, "foo");
630 });
631
632 handle.assert_finished();
633 }
634
635 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
636 #[test]
explicit_root_span_is_root()637 fn explicit_root_span_is_root() {
638 let (subscriber, handle) = subscriber::mock()
639 .new_span(
640 expect::span()
641 .named("foo")
642 .with_ancestry(expect::is_explicit_root()),
643 )
644 .only()
645 .run_with_handle();
646
647 with_default(subscriber, || {
648 tracing::span!(parent: None, Level::TRACE, "foo");
649 });
650
651 handle.assert_finished();
652 }
653
654 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
655 #[test]
explicit_root_span_is_root_regardless_of_ctx()656 fn explicit_root_span_is_root_regardless_of_ctx() {
657 let (subscriber, handle) = subscriber::mock()
658 .new_span(expect::span().named("foo"))
659 .enter(expect::span().named("foo"))
660 .new_span(
661 expect::span()
662 .named("bar")
663 .with_ancestry(expect::is_explicit_root()),
664 )
665 .exit(expect::span().named("foo"))
666 .only()
667 .run_with_handle();
668
669 with_default(subscriber, || {
670 tracing::span!(Level::TRACE, "foo").in_scope(|| {
671 tracing::span!(parent: None, Level::TRACE, "bar");
672 })
673 });
674
675 handle.assert_finished();
676 }
677
678 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
679 #[test]
explicit_child()680 fn explicit_child() {
681 let (subscriber, handle) = subscriber::mock()
682 .new_span(expect::span().named("foo"))
683 .new_span(
684 expect::span()
685 .named("bar")
686 .with_ancestry(expect::has_explicit_parent("foo")),
687 )
688 .only()
689 .run_with_handle();
690
691 with_default(subscriber, || {
692 let foo = tracing::span!(Level::TRACE, "foo");
693 tracing::span!(parent: foo.id(), Level::TRACE, "bar");
694 });
695
696 handle.assert_finished();
697 }
698
699 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
700 #[test]
explicit_child_at_levels()701 fn explicit_child_at_levels() {
702 let (subscriber, handle) = subscriber::mock()
703 .new_span(expect::span().named("foo"))
704 .new_span(
705 expect::span()
706 .named("a")
707 .with_ancestry(expect::has_explicit_parent("foo")),
708 )
709 .new_span(
710 expect::span()
711 .named("b")
712 .with_ancestry(expect::has_explicit_parent("foo")),
713 )
714 .new_span(
715 expect::span()
716 .named("c")
717 .with_ancestry(expect::has_explicit_parent("foo")),
718 )
719 .new_span(
720 expect::span()
721 .named("d")
722 .with_ancestry(expect::has_explicit_parent("foo")),
723 )
724 .new_span(
725 expect::span()
726 .named("e")
727 .with_ancestry(expect::has_explicit_parent("foo")),
728 )
729 .only()
730 .run_with_handle();
731
732 with_default(subscriber, || {
733 let foo = tracing::span!(Level::TRACE, "foo");
734 tracing::trace_span!(parent: foo.id(), "a");
735 tracing::debug_span!(parent: foo.id(), "b");
736 tracing::info_span!(parent: foo.id(), "c");
737 tracing::warn_span!(parent: foo.id(), "d");
738 tracing::error_span!(parent: foo.id(), "e");
739 });
740
741 handle.assert_finished();
742 }
743
744 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
745 #[test]
explicit_child_regardless_of_ctx()746 fn explicit_child_regardless_of_ctx() {
747 let (subscriber, handle) = subscriber::mock()
748 .new_span(expect::span().named("foo"))
749 .new_span(expect::span().named("bar"))
750 .enter(expect::span().named("bar"))
751 .new_span(
752 expect::span()
753 .named("baz")
754 .with_ancestry(expect::has_explicit_parent("foo")),
755 )
756 .exit(expect::span().named("bar"))
757 .only()
758 .run_with_handle();
759
760 with_default(subscriber, || {
761 let foo = tracing::span!(Level::TRACE, "foo");
762 tracing::span!(Level::TRACE, "bar")
763 .in_scope(|| tracing::span!(parent: foo.id(), Level::TRACE, "baz"))
764 });
765
766 handle.assert_finished();
767 }
768
769 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
770 #[test]
contextual_root()771 fn contextual_root() {
772 let (subscriber, handle) = subscriber::mock()
773 .new_span(
774 expect::span()
775 .named("foo")
776 .with_ancestry(expect::is_contextual_root()),
777 )
778 .only()
779 .run_with_handle();
780
781 with_default(subscriber, || {
782 tracing::span!(Level::TRACE, "foo");
783 });
784
785 handle.assert_finished();
786 }
787
788 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
789 #[test]
contextual_child()790 fn contextual_child() {
791 let (subscriber, handle) = subscriber::mock()
792 .new_span(expect::span().named("foo"))
793 .enter(expect::span().named("foo"))
794 .new_span(
795 expect::span()
796 .named("bar")
797 .with_ancestry(expect::has_contextual_parent("foo")),
798 )
799 .exit(expect::span().named("foo"))
800 .only()
801 .run_with_handle();
802
803 with_default(subscriber, || {
804 tracing::span!(Level::TRACE, "foo").in_scope(|| {
805 tracing::span!(Level::TRACE, "bar");
806 })
807 });
808
809 handle.assert_finished();
810 }
811
812 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
813 #[test]
display_shorthand()814 fn display_shorthand() {
815 let (subscriber, handle) = subscriber::mock()
816 .new_span(
817 expect::span().named("my_span").with_fields(
818 expect::field("my_field")
819 .with_value(&display("hello world"))
820 .only(),
821 ),
822 )
823 .only()
824 .run_with_handle();
825 with_default(subscriber, || {
826 tracing::span!(Level::TRACE, "my_span", my_field = %"hello world");
827 });
828
829 handle.assert_finished();
830 }
831
832 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
833 #[test]
debug_shorthand()834 fn debug_shorthand() {
835 let (subscriber, handle) = subscriber::mock()
836 .new_span(
837 expect::span().named("my_span").with_fields(
838 expect::field("my_field")
839 .with_value(&debug("hello world"))
840 .only(),
841 ),
842 )
843 .only()
844 .run_with_handle();
845 with_default(subscriber, || {
846 tracing::span!(Level::TRACE, "my_span", my_field = ?"hello world");
847 });
848
849 handle.assert_finished();
850 }
851
852 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
853 #[test]
both_shorthands()854 fn both_shorthands() {
855 let (subscriber, handle) = subscriber::mock()
856 .new_span(
857 expect::span().named("my_span").with_fields(
858 expect::field("display_field")
859 .with_value(&display("hello world"))
860 .and(expect::field("debug_field").with_value(&debug("hello world")))
861 .only(),
862 ),
863 )
864 .only()
865 .run_with_handle();
866 with_default(subscriber, || {
867 tracing::span!(Level::TRACE, "my_span", display_field = %"hello world", debug_field = ?"hello world");
868 });
869
870 handle.assert_finished();
871 }
872
873 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
874 #[test]
constant_field_name()875 fn constant_field_name() {
876 let (subscriber, handle) = subscriber::mock()
877 .new_span(
878 expect::span().named("my_span").with_fields(
879 expect::field("foo")
880 .with_value(&"bar")
881 .and(expect::field("constant string").with_value(&"also works"))
882 .and(expect::field("foo.bar").with_value(&"baz"))
883 .only(),
884 ),
885 )
886 .only()
887 .run_with_handle();
888
889 with_default(subscriber, || {
890 const FOO: &str = "foo";
891 tracing::span!(
892 Level::TRACE,
893 "my_span",
894 { std::convert::identity(FOO) } = "bar",
895 { "constant string" } = "also works",
896 foo.bar = "baz",
897 );
898 });
899
900 handle.assert_finished();
901 }
902
903 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
904 #[test]
keyword_ident_in_field_name_span_macro()905 fn keyword_ident_in_field_name_span_macro() {
906 #[derive(Debug)]
907 struct Foo;
908
909 let (subscriber, handle) = subscriber::mock()
910 .new_span(expect::span().with_fields(expect::field("self").with_value(&debug(Foo)).only()))
911 .only()
912 .run_with_handle();
913
914 with_default(subscriber, || {
915 error_span!("span", self = ?Foo);
916 });
917 handle.assert_finished();
918 }
919