From 855e5b88309ad7753a59c51b688a9d765f1f263d Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 7 Sep 2026 14:06:54 +0200 Subject: [PATCH] tracing: serialize `tracing_task` tests (#8428) --- tokio/tests/tracing_task.rs | 317 +++++++++++++++++++----------------- 1 file changed, 170 insertions(+), 147 deletions(-) diff --git a/tokio/tests/tracing_task.rs b/tokio/tests/tracing_task.rs index 0cc9666af..9727c3307 100644 --- a/tokio/tests/tracing_task.rs +++ b/tokio/tests/tracing_task.rs @@ -10,166 +10,189 @@ use std::{mem, time::Duration}; use tokio::task; use tracing_mock::{expect, span::NewSpan, subscriber}; -#[tokio::test] -async fn task_spawn_creates_span() { - let task_span = expect::span() - .named("runtime.spawn") - .with_target("tokio::task"); +static TEST_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); - let (subscriber, handle) = subscriber::mock() - .new_span(&task_span) - .enter(&task_span) - .exit(&task_span) - // The task span is entered once more when it gets dropped - .enter(&task_span) - .exit(&task_span) - .drop_span(task_span) - .run_with_handle(); - - { - let _guard = tracing::subscriber::set_default(subscriber); - tokio::spawn(futures::future::ready(())) - .await - .expect("failed to await join handle"); - } - - handle.assert_finished(); +fn run_test(f: impl FnOnce() -> F) -> F::Output { + let _lock = TEST_MUTEX.lock().unwrap_or_else(|e| e.into_inner()); + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(f()) } -#[tokio::test] -async fn task_spawn_loc_file_recorded() { - let task_span = expect::span() - .named("runtime.spawn") - .with_target("tokio::task") - .with_fields(expect::field("loc.file").with_value(&file!())); +#[test] +fn task_spawn_creates_span() { + run_test(|| async { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task"); - let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + let (subscriber, handle) = subscriber::mock() + .new_span(&task_span) + .enter(&task_span) + .exit(&task_span) + // The task span is entered once more when it gets dropped + .enter(&task_span) + .exit(&task_span) + .drop_span(task_span) + .run_with_handle(); - { - let _guard = tracing::subscriber::set_default(subscriber); - - tokio::spawn(futures::future::ready(())) - .await - .expect("failed to await join handle"); - } - - handle.assert_finished(); -} - -#[tokio::test] -async fn task_builder_name_recorded() { - let task_span = expect_task_named("test-task"); - - let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); - - { - let _guard = tracing::subscriber::set_default(subscriber); - task::Builder::new() - .name("test-task") - .spawn(futures::future::ready(())) - .unwrap() - .await - .expect("failed to await join handle"); - } - - handle.assert_finished(); -} - -#[tokio::test] -async fn task_builder_loc_file_recorded() { - let task_span = expect::span() - .named("runtime.spawn") - .with_target("tokio::task") - .with_fields(expect::field("loc.file").with_value(&file!())); - - let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); - - { - let _guard = tracing::subscriber::set_default(subscriber); - - task::Builder::new() - .spawn(futures::future::ready(())) - .unwrap() - .await - .expect("failed to await join handle"); - } - - handle.assert_finished(); -} - -#[tokio::test] -async fn task_spawn_sizes_recorded() { - let future = futures::future::ready(()); - let size = mem::size_of_val(&future) as u64; - - let task_span = expect::span() - .named("runtime.spawn") - .with_target("tokio::task") - // TODO(hds): check that original_size.bytes is NOT recorded when this can be done in - // tracing-mock without listing every other field. - .with_fields(expect::field("size.bytes").with_value(&size)); - - let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); - - { - let _guard = tracing::subscriber::set_default(subscriber); - - task::Builder::new() - .spawn(future) - .unwrap() - .await - .expect("failed to await join handle"); - } - - handle.assert_finished(); -} - -#[tokio::test] -async fn task_big_spawn_sizes_recorded() { - let future = { - async fn big() { - let mut a = [0_u8; N]; - for (idx, item) in a.iter_mut().enumerate() { - *item = (idx % 256) as u8; - } - tokio::time::sleep(Duration::from_millis(10)).await; - for (idx, item) in a.iter_mut().enumerate() { - assert_eq!(*item, (idx % 256) as u8); - } + { + let _guard = tracing::subscriber::set_default(subscriber); + tokio::spawn(futures::future::ready(())) + .await + .expect("failed to await join handle"); } - // This is larger than the release auto-boxing threshold - big::<20_000>() - }; + handle.assert_finished(); + }); +} - fn boxed_size(_: &T) -> usize { - mem::size_of::>() - } - let size = mem::size_of_val(&future) as u64; - let boxed_size = boxed_size(&future); +#[test] +fn task_spawn_loc_file_recorded() { + run_test(|| async { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_fields(expect::field("loc.file").with_value(&file!())); - let task_span = expect::span() - .named("runtime.spawn") - .with_target("tokio::task") - .with_fields( - expect::field("size.bytes") - .with_value(&boxed_size) - .and(expect::field("original_size.bytes").with_value(&size)), - ); + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); - let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + { + let _guard = tracing::subscriber::set_default(subscriber); - { - let _guard = tracing::subscriber::set_default(subscriber); + tokio::spawn(futures::future::ready(())) + .await + .expect("failed to await join handle"); + } - task::Builder::new() - .spawn(future) - .unwrap() - .await - .expect("failed to await join handle"); - } + handle.assert_finished(); + }); +} - handle.assert_finished(); +#[test] +fn task_builder_name_recorded() { + run_test(|| async { + let task_span = expect_task_named("test-task"); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + task::Builder::new() + .name("test-task") + .spawn(futures::future::ready(())) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); + }); +} + +#[test] +fn task_builder_loc_file_recorded() { + run_test(|| async { + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_fields(expect::field("loc.file").with_value(&file!())); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + + task::Builder::new() + .spawn(futures::future::ready(())) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); + }); +} + +#[test] +fn task_spawn_sizes_recorded() { + run_test(|| async { + let future = futures::future::ready(()); + let size = mem::size_of_val(&future) as u64; + + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + // TODO(hds): check that original_size.bytes is NOT recorded when this can be done in + // tracing-mock without listing every other field. + .with_fields(expect::field("size.bytes").with_value(&size)); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + + task::Builder::new() + .spawn(future) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); + }); +} + +#[test] +fn task_big_spawn_sizes_recorded() { + run_test(|| async { + let future = { + async fn big() { + let mut a = [0_u8; N]; + for (idx, item) in a.iter_mut().enumerate() { + *item = (idx % 256) as u8; + } + tokio::time::sleep(Duration::from_millis(10)).await; + for (idx, item) in a.iter_mut().enumerate() { + assert_eq!(*item, (idx % 256) as u8); + } + } + + // This is larger than the release auto-boxing threshold + big::<20_000>() + }; + + fn boxed_size(_: &T) -> usize { + mem::size_of::>() + } + let size = mem::size_of_val(&future) as u64; + let boxed_size = boxed_size(&future); + + let task_span = expect::span() + .named("runtime.spawn") + .with_target("tokio::task") + .with_fields( + expect::field("size.bytes") + .with_value(&boxed_size) + .and(expect::field("original_size.bytes").with_value(&size)), + ); + + let (subscriber, handle) = subscriber::mock().new_span(task_span).run_with_handle(); + + { + let _guard = tracing::subscriber::set_default(subscriber); + + task::Builder::new() + .spawn(future) + .unwrap() + .await + .expect("failed to await join handle"); + } + + handle.assert_finished(); + }); } /// Expect a task with name