Source code
Revision control
Copy as Markdown
Other Tools
#![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());
}