blob: e4804ec6740f7494330b9e9aa45e404d44a88bd5 [file] [log] [blame]
#![warn(rust_2018_idioms)]
#![cfg(feature = "full")]
use tokio::time::{self, Duration, Instant};
use tokio_test::{assert_pending, assert_ready, task};
macro_rules! assert_elapsed {
($now:expr, $ms:expr) => {{
let elapsed = $now.elapsed();
let lower = ms($ms);
// Handles ms rounding
assert!(
elapsed >= lower && elapsed <= lower + ms(1),
"actual = {:?}, expected = {:?}",
elapsed,
lower
);
}};
}
#[tokio::test]
async fn immediate_delay() {
time::pause();
let now = Instant::now();
// Ready!
time::delay_until(now).await;
assert_elapsed!(now, 0);
}
#[tokio::test]
async fn delayed_delay_level_0() {
time::pause();
for &i in &[1, 10, 60] {
let now = Instant::now();
time::delay_until(now + ms(i)).await;
assert_elapsed!(now, i);
}
}
#[tokio::test]
async fn sub_ms_delayed_delay() {
time::pause();
for _ in 0..5 {
let now = Instant::now();
let deadline = now + ms(1) + Duration::new(0, 1);
time::delay_until(deadline).await;
assert_elapsed!(now, 1);
}
}
#[tokio::test]
async fn delayed_delay_wrapping_level_0() {
time::pause();
time::delay_for(ms(5)).await;
let now = Instant::now();
time::delay_until(now + ms(60)).await;
assert_elapsed!(now, 60);
}
#[tokio::test]
async fn reset_future_delay_before_fire() {
time::pause();
let now = Instant::now();
let mut delay = task::spawn(time::delay_until(now + ms(100)));
assert_pending!(delay.poll());
let mut delay = delay.into_inner();
delay.reset(Instant::now() + ms(200));
delay.await;
assert_elapsed!(now, 200);
}
#[tokio::test]
async fn reset_past_delay_before_turn() {
time::pause();
let now = Instant::now();
let mut delay = task::spawn(time::delay_until(now + ms(100)));
assert_pending!(delay.poll());
let mut delay = delay.into_inner();
delay.reset(now + ms(80));
delay.await;
assert_elapsed!(now, 80);
}
#[tokio::test]
async fn reset_past_delay_before_fire() {
time::pause();
let now = Instant::now();
let mut delay = task::spawn(time::delay_until(now + ms(100)));
assert_pending!(delay.poll());
let mut delay = delay.into_inner();
time::delay_for(ms(10)).await;
delay.reset(now + ms(80));
delay.await;
assert_elapsed!(now, 80);
}
#[tokio::test]
async fn reset_future_delay_after_fire() {
time::pause();
let now = Instant::now();
let mut delay = time::delay_until(now + ms(100));
(&mut delay).await;
assert_elapsed!(now, 100);
delay.reset(now + ms(110));
delay.await;
assert_elapsed!(now, 110);
}
#[tokio::test]
async fn reset_delay_to_past() {
time::pause();
let now = Instant::now();
let mut delay = task::spawn(time::delay_until(now + ms(100)));
assert_pending!(delay.poll());
time::delay_for(ms(50)).await;
assert!(!delay.is_woken());
delay.reset(now + ms(40));
assert!(delay.is_woken());
assert_ready!(delay.poll());
}
#[test]
#[should_panic]
fn creating_delay_outside_of_context() {
let now = Instant::now();
// This creates a delay outside of the context of a mock timer. This tests
// that it will panic.
let _fut = time::delay_until(now + ms(500));
}
#[should_panic]
#[tokio::test]
async fn greater_than_max() {
const YR_5: u64 = 5 * 365 * 24 * 60 * 60 * 1000;
time::delay_until(Instant::now() + ms(YR_5)).await;
}
const NUM_LEVELS: usize = 6;
const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
#[should_panic]
#[tokio::test]
async fn exactly_max() {
// TODO: this should not panic but `time::ms()` is acting up
time::delay_for(ms(MAX_DURATION)).await;
}
#[tokio::test]
async fn no_out_of_bounds_close_to_max() {
time::pause();
time::delay_for(ms(MAX_DURATION - 1)).await;
}
fn ms(n: u64) -> Duration {
Duration::from_millis(n)
}