simulation 0.0.1

Framework for deterministic simulation testing.
use std::{
    sync::{Arc, Mutex},
    time::{Duration, Instant},
};
use tokio_executor::park::{Park, Unpark};
use tokio_timer::clock::{Clock, Now};

#[derive(Clone, Debug)]
pub(crate) struct MockClock {
    inner: Inner,
    clock: Clock,
}

impl MockClock {
    pub(crate) fn wrap_park<P>(park: P) -> (Self, MockPark<P>)
    where
        P: Park,
    {
        let state = State {
            base: Instant::now(),
            advance: Duration::from_millis(0),
        };
        let state = Arc::new(Mutex::new(state));
        let now = MockNow {
            inner: Arc::clone(&state),
        };
        let clock = Clock::new_with_now(now);
        let wrapped_park = MockPark {
            inner: Arc::clone(&state),
            inner_park: park,
        };
        (
            Self {
                inner: Arc::clone(&state),
                clock,
            },
            wrapped_park,
        )
    }
    pub(crate) fn now(&self) -> Instant {
        self.inner.lock().unwrap().now()
    }

    pub(crate) fn get_clock(&self) -> Clock {
        self.clock.clone()
    }

    pub fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce() -> R,
    {
        let clock = self.get_clock();
        ::tokio_timer::clock::with_default(&clock, || f())
    }
}
#[derive(Debug)]
struct State {
    base: Instant,
    advance: Duration,
}

impl State {
    fn now(&self) -> Instant {
        self.base + self.advance
    }
    fn advance(&mut self, duration: Duration) {
        self.advance += duration;
    }
}

type Inner = Arc<Mutex<State>>;

#[derive(Debug, Clone)]
pub(crate) struct MockNow {
    inner: Inner,
}

impl Now for MockNow {
    fn now(&self) -> Instant {
        self.inner.lock().unwrap().now()
    }
}

#[derive(Debug, Clone)]
pub(crate) struct MockPark<P> {
    inner: Inner,
    inner_park: P,
}

impl<P> Park for MockPark<P>
where
    P: Park,
{
    type Unpark = MockUnpark;
    type Error = P::Error;
    fn unpark(&self) -> Self::Unpark {
        let unpark = self.inner_park.unpark();
        MockUnpark {
            unpark: Box::new(unpark),
            _inner: self.inner.clone(),
        }
    }
    fn park(&mut self) -> Result<(), Self::Error> {
        self.inner_park.park()
    }
    fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
        self.inner.lock().unwrap().advance(duration);
        self.inner_park.park_timeout(Duration::from_millis(0))
    }
}

pub(crate) struct MockUnpark {
    unpark: Box<dyn Unpark>,
    _inner: Inner,
}

impl Unpark for MockUnpark {
    fn unpark(&self) {
        self.unpark.unpark()
    }
}