1use futures::{future::lazy, Future};
25use std::marker::PhantomData;
26use std::rc::Rc;
27use std::sync::{Arc, Mutex};
28use std::time::{Duration, Instant};
29use tokio_executor::park::{Park, Unpark};
30use tokio_timer::clock::{Clock, Now};
31use tokio_timer::Timer;
32
33pub fn mock<F, R>(f: F) -> R
35where
36 F: FnOnce(&mut Handle) -> R,
37{
38 let mut mock = MockClock::new();
39 mock.enter(f)
40}
41
42pub fn mock_at<F, R>(instant: Instant, f: F) -> R
44where
45 F: FnOnce(&mut Handle) -> R,
46{
47 let mut mock = MockClock::with_instant(instant);
48 mock.enter(f)
49}
50
51#[derive(Debug)]
56pub struct MockClock {
57 time: MockTime,
58 clock: Clock,
59}
60
61#[derive(Debug)]
63pub struct Handle {
64 timer: Timer<MockPark>,
65 time: MockTime,
66}
67
68type Inner = Arc<Mutex<State>>;
69
70#[derive(Debug, Clone)]
71struct MockTime {
72 inner: Inner,
73 _pd: PhantomData<Rc<()>>,
74}
75
76#[derive(Debug)]
77struct MockNow {
78 inner: Inner,
79}
80
81#[derive(Debug)]
82struct MockPark {
83 inner: Inner,
84 _pd: PhantomData<Rc<()>>,
85}
86
87#[derive(Debug)]
88struct MockUnpark {
89 inner: Inner,
90}
91
92#[derive(Debug)]
93struct State {
94 base: Instant,
95 advance: Duration,
96 unparked: bool,
97 park_for: Option<Duration>,
98}
99
100impl MockClock {
101 pub fn new() -> Self {
103 MockClock::with_instant(Instant::now())
104 }
105
106 pub fn with_duration(duration: Duration) -> Self {
110 let instant = Instant::now() + duration;
111 MockClock::with_instant(instant)
112 }
113
114 pub fn with_instant(instant: Instant) -> Self {
116 let time = MockTime::new(instant);
117 let clock = Clock::new_with_now(time.mock_now());
118
119 MockClock { time, clock }
120 }
121
122 pub fn enter<F, R>(&mut self, f: F) -> R
124 where
125 F: FnOnce(&mut Handle) -> R,
126 {
127 let mut enter = ::tokio_executor::enter().unwrap();
128
129 ::tokio_timer::clock::with_default(&self.clock, &mut enter, |enter| {
130 let park = self.time.mock_park();
131 let timer = Timer::new(park);
132 let handle = timer.handle();
133 let time = self.time.clone();
134
135 ::tokio_timer::with_default(&handle, enter, |_| {
136 let mut handle = Handle::new(timer, time);
137 lazy(|| Ok::<_, ()>(f(&mut handle))).wait().unwrap()
138 })
139 })
140 }
141}
142
143impl Handle {
144 pub(self) fn new(timer: Timer<MockPark>, time: MockTime) -> Self {
145 Handle { timer, time }
146 }
147
148 pub fn turn(&mut self, duration: Option<Duration>) {
150 self.timer.turn(duration).unwrap();
151 }
152
153 pub fn advance(&mut self, duration: Duration) {
155 let inner = self.timer.get_park().inner.clone();
156 let deadline = inner.lock().unwrap().now() + duration;
157
158 while inner.lock().unwrap().now() < deadline {
159 let dur = deadline - inner.lock().unwrap().now();
160 self.turn(Some(dur));
161 }
162 }
163
164 pub fn now(&mut self) -> Instant {
166 self.time.now()
167 }
168}
169
170impl MockTime {
171 pub(crate) fn new(now: Instant) -> MockTime {
172 let state = State {
173 base: now,
174 advance: Duration::default(),
175 unparked: false,
176 park_for: None,
177 };
178
179 MockTime {
180 inner: Arc::new(Mutex::new(state)),
181 _pd: PhantomData,
182 }
183 }
184
185 pub(crate) fn mock_now(&self) -> MockNow {
186 let inner = self.inner.clone();
187 MockNow { inner }
188 }
189
190 pub(crate) fn mock_park(&self) -> MockPark {
191 let inner = self.inner.clone();
192 MockPark {
193 inner,
194 _pd: PhantomData,
195 }
196 }
197
198 pub(crate) fn now(&self) -> Instant {
199 self.inner.lock().unwrap().now()
200 }
201}
202
203impl State {
204 fn now(&self) -> Instant {
205 self.base + self.advance
206 }
207
208 fn advance(&mut self, duration: Duration) {
209 self.advance += duration;
210 }
211}
212
213impl Park for MockPark {
214 type Unpark = MockUnpark;
215 type Error = ();
216
217 fn unpark(&self) -> Self::Unpark {
218 let inner = self.inner.clone();
219 MockUnpark { inner }
220 }
221
222 fn park(&mut self) -> Result<(), Self::Error> {
223 let mut inner = self.inner.lock().map_err(|_| ())?;
224
225 let duration = inner.park_for.take().expect("call park_for first");
226
227 inner.advance(duration);
228 Ok(())
229 }
230
231 fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> {
232 let mut inner = self.inner.lock().unwrap();
233
234 if let Some(duration) = inner.park_for.take() {
235 inner.advance(duration);
236 } else {
237 inner.advance(duration);
238 }
239
240 Ok(())
241 }
242}
243
244impl Unpark for MockUnpark {
245 fn unpark(&self) {
246 if let Ok(mut inner) = self.inner.lock() {
247 inner.unparked = true;
248 }
249 }
250}
251
252impl Now for MockNow {
253 fn now(&self) -> Instant {
254 self.inner.lock().unwrap().now()
255 }
256}