mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-28 12:10:37 +00:00

This patch implements `Default` for `tokio_timer::Handle`. It returns a `Handle` instance that is not bound to a specific timer. Instead, it will use the timer for the current execution context. This is the same strategy used by `tokio_reactor::Handle`. Fixes #547
506 lines
12 KiB
Rust
506 lines
12 KiB
Rust
extern crate futures;
|
|
extern crate tokio_executor;
|
|
extern crate tokio_timer;
|
|
|
|
#[macro_use]
|
|
mod support;
|
|
use support::*;
|
|
|
|
use tokio_timer::*;
|
|
use tokio_timer::timer::Handle;
|
|
|
|
use futures::Future;
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
#[test]
|
|
fn immediate_delay() {
|
|
mocked(|timer, time| {
|
|
// Create `Delay` that elapsed immediately.
|
|
let mut delay = Delay::new(time.now());
|
|
|
|
// Ready!
|
|
assert_ready!(delay);
|
|
|
|
// Turn the timer, it runs for the elapsed time
|
|
turn(timer, ms(1000));
|
|
|
|
// The time has not advanced. The `turn` completed immediately.
|
|
assert_eq!(time.advanced(), ms(1000));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn delayed_delay_level_0() {
|
|
for &i in &[1, 10, 60] {
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(i));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(i));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn sub_ms_delayed_delay() {
|
|
mocked(|timer, time| {
|
|
for _ in 0..5 {
|
|
let deadline = time.now()
|
|
+ Duration::from_millis(1)
|
|
+ Duration::new(0, 1);
|
|
|
|
let mut delay = Delay::new(deadline);
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_ready!(delay);
|
|
|
|
assert!(time.now() >= deadline);
|
|
|
|
time.advance(Duration::new(0, 1));
|
|
}
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn delayed_delay_wrapping_level_0() {
|
|
mocked(|timer, time| {
|
|
turn(timer, ms(5));
|
|
assert_eq!(time.advanced(), ms(5));
|
|
|
|
let mut delay = Delay::new(time.now() + ms(60));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(64));
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(65));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn timer_wrapping_with_higher_levels() {
|
|
mocked(|timer, time| {
|
|
// Set delay to hit level 1
|
|
let mut s1 = Delay::new(time.now() + ms(64));
|
|
assert_not_ready!(s1);
|
|
|
|
// Turn a bit
|
|
turn(timer, ms(5));
|
|
|
|
// Set timeout such that it will hit level 0, but wrap
|
|
let mut s2 = Delay::new(time.now() + ms(60));
|
|
assert_not_ready!(s2);
|
|
|
|
// This should result in s1 firing
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(64));
|
|
|
|
assert_ready!(s1);
|
|
assert_not_ready!(s2);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(65));
|
|
|
|
assert_ready!(s2);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn delay_with_deadline_in_past() {
|
|
mocked(|timer, time| {
|
|
// Create `Delay` that elapsed immediately.
|
|
let mut delay = Delay::new(time.now() - ms(100));
|
|
|
|
// Even though the delay expires in the past, it is not ready yet
|
|
// because the timer must observe it.
|
|
assert_ready!(delay);
|
|
|
|
// Turn the timer, it runs for the elapsed time
|
|
turn(timer, ms(1000));
|
|
|
|
// The time has not advanced. The `turn` completed immediately.
|
|
assert_eq!(time.advanced(), ms(1000));
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn delayed_delay_level_1() {
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(234));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer, this will wake up to cascade the timer down.
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(192));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer again
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(234));
|
|
|
|
// The delay has elapsed.
|
|
assert_ready!(delay);
|
|
});
|
|
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(234));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer with a smaller timeout than the cascade.
|
|
turn(timer, ms(100));
|
|
assert_eq!(time.advanced(), ms(100));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer, this will wake up to cascade the timer down.
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(192));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer again
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(234));
|
|
|
|
// The delay has elapsed.
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
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 still expire.
|
|
let mut delay = Delay::new(now + ms(500));
|
|
|
|
mocked_with_now(now, |timer, time| {
|
|
// This registers the delay with the timer
|
|
assert_not_ready!(delay);
|
|
|
|
// Wait some time... the timer is cascading
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(448));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(500));
|
|
|
|
// The delay has elapsed
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn concurrently_set_two_timers_second_one_shorter() {
|
|
mocked(|timer, time| {
|
|
let mut delay1 = Delay::new(time.now() + ms(500));
|
|
let mut delay2 = Delay::new(time.now() + ms(200));
|
|
|
|
// The delay has not elapsed
|
|
assert_not_ready!(delay1);
|
|
assert_not_ready!(delay2);
|
|
|
|
// Delay until a cascade
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(192));
|
|
|
|
// Delay until the second timer.
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(200));
|
|
|
|
// The shorter delay fires
|
|
assert_ready!(delay2);
|
|
assert_not_ready!(delay1);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(448));
|
|
|
|
assert_not_ready!(delay1);
|
|
|
|
// Turn again, this time the time will advance to the second delay
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(500));
|
|
|
|
assert_ready!(delay1);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn short_delay() {
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(1));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
// Turn the timer, but not enough time will go by.
|
|
turn(timer, None);
|
|
|
|
// The delay has elapsed.
|
|
assert_ready!(delay);
|
|
|
|
// The time has advanced to the point of the delay elapsing.
|
|
assert_eq!(time.advanced(), ms(1));
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn sorta_long_delay() {
|
|
const MIN_5: u64 = 5 * 60 * 1000;
|
|
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(MIN_5));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
let cascades = &[
|
|
262_144,
|
|
262_144 + 9 * 4096,
|
|
262_144 + 9 * 4096 + 15 * 64,
|
|
];
|
|
|
|
for &elapsed in cascades {
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(elapsed));
|
|
|
|
assert_not_ready!(delay);
|
|
}
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(MIN_5));
|
|
|
|
// The delay has elapsed.
|
|
assert_ready!(delay);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn very_long_delay() {
|
|
const MO_5: u64 = 5 * 30 * 24 * 60 * 60 * 1000;
|
|
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(MO_5));
|
|
|
|
// The delay has not elapsed.
|
|
assert_not_ready!(delay);
|
|
|
|
let cascades = &[
|
|
12_884_901_888,
|
|
12_952_010_752,
|
|
12_959_875_072,
|
|
12_959_997_952,
|
|
];
|
|
|
|
for &elapsed in cascades {
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(elapsed));
|
|
|
|
assert_not_ready!(delay);
|
|
}
|
|
|
|
// Turn the timer, but not enough time will go by.
|
|
turn(timer, None);
|
|
|
|
// The time has advanced to the point of the delay elapsing.
|
|
assert_eq!(time.advanced(), ms(MO_5));
|
|
|
|
// The delay has elapsed.
|
|
assert_ready!(delay);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn greater_than_max() {
|
|
const YR_5: u64 = 5 * 365 * 24 * 60 * 60 * 1000;
|
|
|
|
mocked(|timer, time| {
|
|
// Create a `Delay` that elapses in the future
|
|
let mut delay = Delay::new(time.now() + ms(YR_5));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(0));
|
|
|
|
assert!(delay.poll().is_err());
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn unpark_is_delayed() {
|
|
mocked(|timer, time| {
|
|
let mut delay1 = Delay::new(time.now() + ms(100));
|
|
let mut delay2 = Delay::new(time.now() + ms(101));
|
|
let mut delay3 = Delay::new(time.now() + ms(200));
|
|
|
|
assert_not_ready!(delay1);
|
|
assert_not_ready!(delay2);
|
|
assert_not_ready!(delay3);
|
|
|
|
time.park_for(ms(500));
|
|
|
|
turn(timer, None);
|
|
|
|
assert_eq!(time.advanced(), ms(500));
|
|
|
|
assert_ready!(delay1);
|
|
assert_ready!(delay2);
|
|
assert_ready!(delay3);
|
|
})
|
|
}
|
|
|
|
#[test]
|
|
fn set_timeout_at_deadline_greater_than_max_timer() {
|
|
const YR_1: u64 = 365 * 24 * 60 * 60 * 1000;
|
|
const YR_5: u64 = 5 * YR_1;
|
|
|
|
mocked(|timer, time| {
|
|
for _ in 0..5 {
|
|
turn(timer, ms(YR_1));
|
|
}
|
|
|
|
let mut delay = Delay::new(time.now() + ms(1));
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), Duration::from_millis(YR_5) + ms(1));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn reset_future_delay_before_fire() {
|
|
mocked(|timer, time| {
|
|
let mut delay = Delay::new(time.now() + ms(100));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
delay.reset(time.now() + ms(200));
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(192));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(200));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn reset_past_delay_before_turn() {
|
|
mocked(|timer, time| {
|
|
let mut delay = Delay::new(time.now() + ms(100));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
delay.reset(time.now() + ms(80));
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(64));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(80));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn reset_past_delay_before_fire() {
|
|
mocked(|timer, time| {
|
|
let mut delay = Delay::new(time.now() + ms(100));
|
|
|
|
assert_not_ready!(delay);
|
|
turn(timer, ms(10));
|
|
|
|
assert_not_ready!(delay);
|
|
delay.reset(time.now() + ms(80));
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(64));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(90));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn reset_future_delay_after_fire() {
|
|
mocked(|timer, time| {
|
|
let mut delay = Delay::new(time.now() + ms(100));
|
|
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(64));
|
|
|
|
turn(timer, None);
|
|
assert_eq!(time.advanced(), ms(100));
|
|
|
|
assert_ready!(delay);
|
|
|
|
delay.reset(time.now() + ms(10));
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1000));
|
|
assert_eq!(time.advanced(), ms(110));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn delay_with_default_handle() {
|
|
let handle = Handle::default();
|
|
let now = Instant::now();
|
|
|
|
let mut delay = handle.delay(now + ms(1));
|
|
|
|
mocked_with_now(now, |timer, _time| {
|
|
assert_not_ready!(delay);
|
|
|
|
turn(timer, ms(1));
|
|
|
|
assert_ready!(delay);
|
|
});
|
|
}
|