#![warn(rust_2018_idioms)] #![cfg(feature = "full")] use tokio::sync::oneshot; use tokio::time::{self, timeout, timeout_at, Instant}; use tokio_test::*; use futures::future::pending; use std::time::Duration; #[tokio::test] async fn simultaneous_deadline_future_completion() { // Create a future that is immediately ready let mut fut = task::spawn(timeout_at(Instant::now(), async {})); // Ready! assert_ready_ok!(fut.poll()); } #[cfg_attr(target_os = "wasi", ignore = "FIXME: `fut.poll()` panics on Wasi")] #[tokio::test] async fn completed_future_past_deadline() { // Wrap it with a deadline let mut fut = task::spawn(timeout_at(Instant::now() - ms(1000), async {})); // Ready! assert_ready_ok!(fut.poll()); } #[tokio::test] async fn future_and_deadline_in_future() { time::pause(); // Not yet complete let (tx, rx) = oneshot::channel(); // Wrap it with a deadline let mut fut = task::spawn(timeout_at(Instant::now() + ms(100), rx)); assert_pending!(fut.poll()); // Turn the timer, it runs for the elapsed time time::advance(ms(90)).await; assert_pending!(fut.poll()); // Complete the future tx.send(()).unwrap(); assert!(fut.is_woken()); assert_ready_ok!(fut.poll()).unwrap(); } #[tokio::test] async fn future_and_timeout_in_future() { time::pause(); // Not yet complete let (tx, rx) = oneshot::channel(); // Wrap it with a deadline let mut fut = task::spawn(timeout(ms(100), rx)); // Ready! assert_pending!(fut.poll()); // Turn the timer, it runs for the elapsed time time::advance(ms(90)).await; assert_pending!(fut.poll()); // Complete the future tx.send(()).unwrap(); assert_ready_ok!(fut.poll()).unwrap(); } #[tokio::test] async fn very_large_timeout() { time::pause(); // Not yet complete let (tx, rx) = oneshot::channel(); // copy-paste unstable `Duration::MAX` let duration_max = Duration::from_secs(u64::MAX) + Duration::from_nanos(999_999_999); // Wrap it with a deadline let mut fut = task::spawn(timeout(duration_max, rx)); // Ready! assert_pending!(fut.poll()); // Turn the timer, it runs for the elapsed time time::advance(Duration::from_secs(86400 * 365 * 10)).await; assert_pending!(fut.poll()); // Complete the future tx.send(()).unwrap(); assert_ready_ok!(fut.poll()).unwrap(); } #[tokio::test] async fn deadline_now_elapses() { use futures::future::pending; time::pause(); // Wrap it with a deadline let mut fut = task::spawn(timeout_at(Instant::now(), pending::<()>())); // Factor in jitter // TODO: don't require this time::advance(ms(1)).await; assert_ready_err!(fut.poll()); } #[tokio::test] async fn deadline_future_elapses() { time::pause(); // Wrap it with a deadline let mut fut = task::spawn(timeout_at(Instant::now() + ms(300), pending::<()>())); assert_pending!(fut.poll()); time::advance(ms(301)).await; assert!(fut.is_woken()); assert_ready_err!(fut.poll()); } fn ms(n: u64) -> Duration { Duration::from_millis(n) } #[tokio::test] async fn timeout_is_not_exhausted_by_future() { let fut = timeout(ms(1), async { let mut buffer = [0u8; 1]; loop { use tokio::io::AsyncReadExt; let _ = tokio::io::empty().read(&mut buffer).await; } }); assert!(fut.await.is_err()); }