summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio-timer/tests/support/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/tokio-timer/tests/support/mod.rs')
-rw-r--r--third_party/rust/tokio-timer/tests/support/mod.rs261
1 files changed, 261 insertions, 0 deletions
diff --git a/third_party/rust/tokio-timer/tests/support/mod.rs b/third_party/rust/tokio-timer/tests/support/mod.rs
new file mode 100644
index 0000000000..244d56b819
--- /dev/null
+++ b/third_party/rust/tokio-timer/tests/support/mod.rs
@@ -0,0 +1,261 @@
+#![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<Rc<()>>,
+}
+
+#[derive(Debug)]
+pub struct MockNow {
+ inner: Inner,
+}
+
+#[derive(Debug)]
+pub struct MockPark {
+ inner: Inner,
+ _p: PhantomData<Rc<()>>,
+}
+
+#[derive(Debug)]
+pub struct MockUnpark {
+ inner: Inner,
+}
+
+type Inner = Arc<Mutex<State>>;
+
+#[derive(Debug)]
+struct State {
+ base: Instant,
+ advance: Duration,
+ unparked: bool,
+ park_for: Option<Duration>,
+}
+
+pub fn ms(num: u64) -> Duration {
+ Duration::from_millis(num)
+}
+
+pub trait IntoTimeout {
+ fn into_timeout(self) -> Option<Duration>;
+}
+
+impl IntoTimeout for Option<Duration> {
+ fn into_timeout(self) -> Self {
+ self
+ }
+}
+
+impl IntoTimeout for Duration {
+ fn into_timeout(self) -> Option<Duration> {
+ Some(self)
+ }
+}
+
+/// Turn the timer state once
+pub fn turn<T: IntoTimeout>(timer: &mut Timer<MockPark>, duration: T) {
+ timer.turn(duration.into_timeout()).unwrap();
+}
+
+/// Advance the timer the specified amount
+pub fn advance(timer: &mut Timer<MockPark>, 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, R>(f: F) -> R
+where
+ F: FnOnce(&mut Timer<MockPark>, &mut MockTime) -> R,
+{
+ mocked_with_now(Instant::now(), f)
+}
+
+pub fn mocked_with_now<F, R>(now: Instant, f: F) -> R
+where
+ F: FnOnce(&mut Timer<MockPark>, &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;
+ }
+}