mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-17 02:10:07 +00:00
151 lines
3.3 KiB
Rust
151 lines
3.3 KiB
Rust
#![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());
|
|
}
|