diff options
Diffstat (limited to 'third_party/rust/tokio/tests/time_timeout.rs')
-rw-r--r-- | third_party/rust/tokio/tests/time_timeout.rs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/third_party/rust/tokio/tests/time_timeout.rs b/third_party/rust/tokio/tests/time_timeout.rs new file mode 100644 index 0000000000..a1ff51e7d2 --- /dev/null +++ b/third_party/rust/tokio/tests/time_timeout.rs @@ -0,0 +1,150 @@ +#![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()); +} + +#[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()); +} |