| extern crate futures; |
| extern crate tokio_executor; |
| extern crate tokio_timer; |
| |
| #[macro_use] |
| mod support; |
| use support::*; |
| |
| use tokio_timer::timer::Handle; |
| use tokio_timer::*; |
| |
| 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); |
| }); |
| } |