From d25778f67d4571f9067a0004133d5a9005b6aedd Mon Sep 17 00:00:00 2001 From: Mattia Pitossi Date: Mon, 20 Oct 2025 14:43:41 +0200 Subject: [PATCH] task: add tests for `task::Builder::spawn_local` (#7697) --- tokio/src/task/builder.rs | 11 +++++++---- tokio/src/task/join_set.rs | 9 +++++---- tokio/tests/task_builder.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/tokio/src/task/builder.rs b/tokio/src/task/builder.rs index 6053352a0..467a70064 100644 --- a/tokio/src/task/builder.rs +++ b/tokio/src/task/builder.rs @@ -118,20 +118,23 @@ impl<'a> Builder<'a> { }) } - /// Spawns `!Send` a task on the current [`LocalSet`] with this builder's - /// settings. + /// Spawns `!Send` a task on the current [`LocalSet`] or [`LocalRuntime`] with + /// this builder's settings. /// /// The spawned future will be run on the same thread that called `spawn_local`. - /// This may only be called from the context of a [local task set][`LocalSet`]. + /// This may only be called from the context of a [local task set][`LocalSet`] + /// or a [`LocalRuntime`]. /// /// # Panics /// - /// This function panics if called outside of a [local task set][`LocalSet`]. + /// This function panics if called outside of a [local task set][`LocalSet`] + /// or a [`LocalRuntime`]. /// /// See [`task::spawn_local`] for more details. /// /// [`task::spawn_local`]: crate::task::spawn_local /// [`LocalSet`]: crate::task::LocalSet + /// [`LocalRuntime`]: crate::runtime::LocalRuntime #[track_caller] pub fn spawn_local(self, future: Fut) -> io::Result> where diff --git a/tokio/src/task/join_set.rs b/tokio/src/task/join_set.rs index db948f168..544d6a234 100644 --- a/tokio/src/task/join_set.rs +++ b/tokio/src/task/join_set.rs @@ -177,7 +177,7 @@ impl JoinSet { /// /// # Panics /// - /// This method panics if it is called outside of a `LocalSet`or `LocalRuntime`. + /// This method panics if it is called outside of a `LocalSet` or `LocalRuntime`. /// /// [`LocalSet`]: crate::task::LocalSet /// [`LocalRuntime`]: crate::runtime::LocalRuntime @@ -748,8 +748,8 @@ impl<'a, T: 'static> Builder<'a, T> { .insert(self.builder.spawn_blocking_on(f, handle)?)) } - /// Spawn the provided task on the current [`LocalSet`] with this builder's - /// settings, and store it in the [`JoinSet`]. + /// Spawn the provided task on the current [`LocalSet`] or [`LocalRuntime`] + /// with this builder's settings, and store it in the [`JoinSet`]. /// /// # Returns /// @@ -757,9 +757,10 @@ impl<'a, T: 'static> Builder<'a, T> { /// /// # Panics /// - /// This method panics if it is called outside of a `LocalSet`. + /// This method panics if it is called outside of a `LocalSet` or `LocalRuntime`. /// /// [`LocalSet`]: crate::task::LocalSet + /// [`LocalRuntime`]: crate::runtime::LocalRuntime /// [`AbortHandle`]: crate::task::AbortHandle #[track_caller] pub fn spawn_local(self, future: F) -> std::io::Result diff --git a/tokio/tests/task_builder.rs b/tokio/tests/task_builder.rs index a2803f0da..f00a3d1e0 100644 --- a/tokio/tests/task_builder.rs +++ b/tokio/tests/task_builder.rs @@ -14,6 +14,34 @@ async fn spawn_with_name() { assert_eq!(result.unwrap(), "task executed"); } +#[tokio::test(flavor = "local")] +async fn spawn_local_on_local_runtime() { + let result = Builder::new() + .spawn_local(async { "task executed" }) + .unwrap() + .await; + + assert_eq!(result.unwrap(), "task executed"); +} + +#[tokio::test] +#[should_panic = "`spawn_local` called from outside of a `task::LocalSet` or `runtime::LocalRuntime`"] +async fn spawn_local_panics_outside_local_set_or_local_runtime() { + let _ = Builder::new() + .spawn_local(async { "task executed" }) + .unwrap() + .await; +} + +#[tokio::test(flavor = "multi_thread")] +#[should_panic = "`spawn_local` called from outside of a `task::LocalSet` or `runtime::LocalRuntime`"] +async fn spawn_local_panics_in_multi_thread_runtime() { + let _ = Builder::new() + .spawn_local(async { "task executed" }) + .unwrap() + .await; +} + #[tokio::test] async fn spawn_blocking_with_name() { let result = Builder::new()