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] |
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] |
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] |
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] |
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] |
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] |
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] |
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" ))] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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 | |