#![allow(unused_macros, unused_imports, dead_code, deprecated)] use tokio_executor::park::{Park, Unpark}; use tokio_timer::clock::Now; use tokio_timer::timer::Timer; use futures::future::{lazy, Future}; use std::marker::PhantomData; use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; macro_rules! assert_ready { ($f:expr) => {{ use ::futures::Async::*; match $f.poll().unwrap() { Ready(v) => v, NotReady => panic!("NotReady"), } }}; ($f:expr, $($msg:expr),+) => {{ use ::futures::Async::*; match $f.poll().unwrap() { Ready(v) => v, NotReady => { let msg = format!($($msg),+); panic!("NotReady; {}", msg) } } }} } macro_rules! assert_ready_eq { ($f:expr, $expect:expr) => { assert_eq!($f.poll().unwrap(), ::futures::Async::Ready($expect)); }; } macro_rules! assert_not_ready { ($f:expr) => {{ let res = $f.poll().unwrap(); assert!(!res.is_ready(), "actual={:?}", res) }}; ($f:expr, $($msg:expr),+) => {{ let res = $f.poll().unwrap(); if res.is_ready() { let msg = format!($($msg),+); panic!("actual={:?}; {}", res, msg); } }}; } macro_rules! assert_elapsed { ($f:expr) => { assert!($f.poll().unwrap_err().is_elapsed()); }; } #[derive(Debug)] pub struct MockTime { inner: Inner, _p: PhantomData>, } #[derive(Debug)] pub struct MockNow { inner: Inner, } #[derive(Debug)] pub struct MockPark { inner: Inner, _p: PhantomData>, } #[derive(Debug)] pub struct MockUnpark { inner: Inner, } type Inner = Arc>; #[derive(Debug)] struct State { base: Instant, advance: Duration, unparked: bool, park_for: Option, } pub fn ms(num: u64) -> Duration { Duration::from_millis(num) } pub trait IntoTimeout { fn into_timeout(self) -> Option; } impl IntoTimeout for Option { fn into_timeout(self) -> Self { self } } impl IntoTimeout for Duration { fn into_timeout(self) -> Option { Some(self) } } /// Turn the timer state once pub fn turn(timer: &mut Timer, duration: T) { timer.turn(duration.into_timeout()).unwrap(); } /// Advance the timer the specified amount pub fn advance(timer: &mut Timer, duration: Duration) { let inner = timer.get_park().inner.clone(); let deadline = inner.lock().unwrap().now() + duration; while inner.lock().unwrap().now() < deadline { let dur = deadline - inner.lock().unwrap().now(); turn(timer, dur); } } pub fn mocked(f: F) -> R where F: FnOnce(&mut Timer, &mut MockTime) -> R, { mocked_with_now(Instant::now(), f) } pub fn mocked_with_now(now: Instant, f: F) -> R where F: FnOnce(&mut Timer, &mut MockTime) -> R, { let mut time = MockTime::new(now); let park = time.mock_park(); let now = ::tokio_timer::clock::Clock::new_with_now(time.mock_now()); let mut enter = ::tokio_executor::enter().unwrap(); ::tokio_timer::clock::with_default(&now, &mut enter, |enter| { let mut timer = Timer::new(park); let handle = timer.handle(); ::tokio_timer::with_default(&handle, enter, |_| { lazy(|| Ok::<_, ()>(f(&mut timer, &mut time))) .wait() .unwrap() }) }) } impl MockTime { pub fn new(now: Instant) -> MockTime { let state = State { base: now, advance: Duration::default(), unparked: false, park_for: None, }; MockTime { inner: Arc::new(Mutex::new(state)), _p: PhantomData, } } pub fn mock_now(&self) -> MockNow { let inner = self.inner.clone(); MockNow { inner } } pub fn mock_park(&self) -> MockPark { let inner = self.inner.clone(); MockPark { inner, _p: PhantomData, } } pub fn now(&self) -> Instant { self.inner.lock().unwrap().now() } /// Returns the total amount of time the time has been advanced. pub fn advanced(&self) -> Duration { self.inner.lock().unwrap().advance } pub fn advance(&self, duration: Duration) { let mut inner = self.inner.lock().unwrap(); inner.advance(duration); } /// The next call to park_timeout will be for this duration, regardless of /// the timeout passed to `park_timeout`. pub fn park_for(&self, duration: Duration) { self.inner.lock().unwrap().park_for = Some(duration); } } impl Park for MockPark { type Unpark = MockUnpark; type Error = (); fn unpark(&self) -> Self::Unpark { let inner = self.inner.clone(); MockUnpark { inner } } fn park(&mut self) -> Result<(), Self::Error> { let mut inner = self.inner.lock().map_err(|_| ())?; let duration = inner.park_for.take().expect("call park_for first"); inner.advance(duration); Ok(()) } fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> { let mut inner = self.inner.lock().unwrap(); if let Some(duration) = inner.park_for.take() { inner.advance(duration); } else { inner.advance(duration); } Ok(()) } } impl Unpark for MockUnpark { fn unpark(&self) { if let Ok(mut inner) = self.inner.lock() { inner.unparked = true; } } } impl Now for MockNow { fn now(&self) -> Instant { self.inner.lock().unwrap().now() } } impl State { fn now(&self) -> Instant { self.base + self.advance } fn advance(&mut self, duration: Duration) { self.advance += duration; } }