time: add docs about auto-advance and when to use sleep (#7858)

This commit is contained in:
Andrea Bozzo
2026-01-19 09:12:37 +01:00
committed by GitHub
parent bf185b61ff
commit 8cfa309126
+62
View File
@@ -124,8 +124,39 @@ cfg_test_util! {
/// other timer-backed primitives can cause the runtime to advance the /// other timer-backed primitives can cause the runtime to advance the
/// current time when awaited. /// current time when awaited.
/// ///
/// # Preventing auto-advance
///
/// In some testing scenarios, you may want to keep the clock paused without
/// auto-advancing, even while waiting for I/O or other asynchronous operations.
/// This can be achieved by using [`spawn_blocking`] to wrap your I/O operations.
///
/// When a blocking task is running, the clock's auto-advance is temporarily
/// inhibited. This allows you to wait for I/O to complete while keeping the
/// paused clock stationary:
///
/// ```ignore
/// use tokio::time::{Duration, Instant};
/// use tokio::task;
///
/// #[tokio::test(start_paused = true)]
/// async fn test_with_io() {
/// let start = Instant::now();
///
/// // The clock will NOT auto-advance while this blocking task runs
/// let result = task::spawn_blocking(|| {
/// // Perform I/O operations here
/// std::thread::sleep(std::time::Duration::from_millis(10));
/// 42
/// }).await.unwrap();
///
/// // Time has not advanced
/// assert_eq!(start.elapsed(), Duration::ZERO);
/// }
/// ```
///
/// [`Sleep`]: crate::time::Sleep /// [`Sleep`]: crate::time::Sleep
/// [`advance`]: crate::time::advance /// [`advance`]: crate::time::advance
/// [`spawn_blocking`]: crate::task::spawn_blocking
#[track_caller] #[track_caller]
pub fn pause() { pub fn pause() {
with_clock(|maybe_clock| { with_clock(|maybe_clock| {
@@ -183,6 +214,37 @@ cfg_test_util! {
/// `advance`. However if they don't, the runtime will poll the task again /// `advance`. However if they don't, the runtime will poll the task again
/// shortly. /// shortly.
/// ///
/// # When to use `sleep` instead
///
/// **Important:** `advance` is designed for testing scenarios where you want to
/// instantly jump forward in time. However, it has limitations that make it
/// unsuitable for certain use cases:
///
/// - **Forcing timeouts:** If you want to reliably trigger a timeout, prefer
/// using [`sleep`] with auto-advance rather than `advance`. The `advance`
/// function jumps time forward but doesn't guarantee that all timers will be
/// processed before your code continues.
///
/// - **Simulating freezes:** If you're trying to simulate a scenario where the
/// program freezes and then resumes, the batch behavior of `advance` may not
/// produce the expected results. All timers that expire during the advance
/// complete simultaneously.
///
/// For most testing scenarios where you want to wait for a duration to pass
/// and have all timers fire in order, use [`sleep`] instead:
///
/// ```ignore
/// use tokio::time::{self, Duration};
///
/// #[tokio::test(start_paused = true)]
/// async fn test_timeout_reliable() {
/// // Use sleep with auto-advance for reliable timeout testing
/// time::sleep(Duration::from_secs(5)).await;
/// // All timers that were scheduled to fire within 5 seconds
/// // have now been processed in order
/// }
/// ```
///
/// # Panics /// # Panics
/// ///
/// Panics if any of the following conditions are met: /// Panics if any of the following conditions are met: