• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use std::future::Future;
5 use std::task::Context;
6 
7 use futures::task::noop_waker_ref;
8 
9 use tokio::time::{self, Duration, Instant};
10 use tokio_test::{assert_pending, assert_ready, task};
11 
12 macro_rules! assert_elapsed {
13     ($now:expr, $ms:expr) => {{
14         let elapsed = $now.elapsed();
15         let lower = ms($ms);
16 
17         // Handles ms rounding
18         assert!(
19             elapsed >= lower && elapsed <= lower + ms(1),
20             "actual = {:?}, expected = {:?}",
21             elapsed,
22             lower
23         );
24     }};
25 }
26 
27 #[tokio::test]
immediate_sleep()28 async fn immediate_sleep() {
29     time::pause();
30 
31     let now = Instant::now();
32 
33     // Ready!
34     time::sleep_until(now).await;
35     assert_elapsed!(now, 0);
36 }
37 
38 #[tokio::test]
is_elapsed()39 async fn is_elapsed() {
40     time::pause();
41 
42     let sleep = time::sleep(Duration::from_millis(50));
43 
44     tokio::pin!(sleep);
45 
46     assert!(!sleep.is_elapsed());
47 
48     assert!(futures::poll!(sleep.as_mut()).is_pending());
49 
50     assert!(!sleep.is_elapsed());
51 
52     sleep.as_mut().await;
53 
54     assert!(sleep.is_elapsed());
55 }
56 
57 #[tokio::test]
delayed_sleep_level_0()58 async fn delayed_sleep_level_0() {
59     time::pause();
60 
61     for &i in &[1, 10, 60] {
62         let now = Instant::now();
63 
64         time::sleep_until(now + ms(i)).await;
65 
66         assert_elapsed!(now, i);
67     }
68 }
69 
70 #[tokio::test]
sub_ms_delayed_sleep()71 async fn sub_ms_delayed_sleep() {
72     time::pause();
73 
74     for _ in 0..5 {
75         let now = Instant::now();
76         let deadline = now + ms(1) + Duration::new(0, 1);
77 
78         time::sleep_until(deadline).await;
79 
80         assert_elapsed!(now, 1);
81     }
82 }
83 
84 #[tokio::test]
delayed_sleep_wrapping_level_0()85 async fn delayed_sleep_wrapping_level_0() {
86     time::pause();
87 
88     time::sleep(ms(5)).await;
89 
90     let now = Instant::now();
91     time::sleep_until(now + ms(60)).await;
92 
93     assert_elapsed!(now, 60);
94 }
95 
96 #[tokio::test]
reset_future_sleep_before_fire()97 async fn reset_future_sleep_before_fire() {
98     time::pause();
99 
100     let now = Instant::now();
101 
102     let mut sleep = task::spawn(Box::pin(time::sleep_until(now + ms(100))));
103     assert_pending!(sleep.poll());
104 
105     let mut sleep = sleep.into_inner();
106 
107     sleep.as_mut().reset(Instant::now() + ms(200));
108     sleep.await;
109 
110     assert_elapsed!(now, 200);
111 }
112 
113 #[tokio::test]
reset_past_sleep_before_turn()114 async fn reset_past_sleep_before_turn() {
115     time::pause();
116 
117     let now = Instant::now();
118 
119     let mut sleep = task::spawn(Box::pin(time::sleep_until(now + ms(100))));
120     assert_pending!(sleep.poll());
121 
122     let mut sleep = sleep.into_inner();
123 
124     sleep.as_mut().reset(now + ms(80));
125     sleep.await;
126 
127     assert_elapsed!(now, 80);
128 }
129 
130 #[tokio::test]
reset_past_sleep_before_fire()131 async fn reset_past_sleep_before_fire() {
132     time::pause();
133 
134     let now = Instant::now();
135 
136     let mut sleep = task::spawn(Box::pin(time::sleep_until(now + ms(100))));
137     assert_pending!(sleep.poll());
138 
139     let mut sleep = sleep.into_inner();
140 
141     time::sleep(ms(10)).await;
142 
143     sleep.as_mut().reset(now + ms(80));
144     sleep.await;
145 
146     assert_elapsed!(now, 80);
147 }
148 
149 #[tokio::test]
reset_future_sleep_after_fire()150 async fn reset_future_sleep_after_fire() {
151     time::pause();
152 
153     let now = Instant::now();
154     let mut sleep = Box::pin(time::sleep_until(now + ms(100)));
155 
156     sleep.as_mut().await;
157     assert_elapsed!(now, 100);
158 
159     sleep.as_mut().reset(now + ms(110));
160     sleep.await;
161     assert_elapsed!(now, 110);
162 }
163 
164 #[tokio::test]
reset_sleep_to_past()165 async fn reset_sleep_to_past() {
166     time::pause();
167 
168     let now = Instant::now();
169 
170     let mut sleep = task::spawn(Box::pin(time::sleep_until(now + ms(100))));
171     assert_pending!(sleep.poll());
172 
173     time::sleep(ms(50)).await;
174 
175     assert!(!sleep.is_woken());
176 
177     sleep.as_mut().reset(now + ms(40));
178 
179     // TODO: is this required?
180     //assert!(sleep.is_woken());
181 
182     assert_ready!(sleep.poll());
183 }
184 
185 #[test]
186 #[should_panic]
creating_sleep_outside_of_context()187 fn creating_sleep_outside_of_context() {
188     let now = Instant::now();
189 
190     // This creates a delay outside of the context of a mock timer. This tests
191     // that it will panic.
192     let _fut = time::sleep_until(now + ms(500));
193 }
194 
195 #[tokio::test]
greater_than_max()196 async fn greater_than_max() {
197     const YR_5: u64 = 5 * 365 * 24 * 60 * 60 * 1000;
198 
199     time::pause();
200     time::sleep_until(Instant::now() + ms(YR_5)).await;
201 }
202 
203 #[tokio::test]
short_sleeps()204 async fn short_sleeps() {
205     for i in 0..10000 {
206         if (i % 10) == 0 {
207             eprintln!("=== {}", i);
208         }
209         tokio::time::sleep(std::time::Duration::from_millis(0)).await;
210     }
211 }
212 
213 #[tokio::test]
multi_long_sleeps()214 async fn multi_long_sleeps() {
215     tokio::time::pause();
216 
217     for _ in 0..5u32 {
218         tokio::time::sleep(Duration::from_secs(
219             // about a year
220             365 * 24 * 3600,
221         ))
222         .await;
223     }
224 
225     let deadline = tokio::time::Instant::now()
226         + Duration::from_secs(
227             // about 10 years
228             10 * 365 * 24 * 3600,
229         );
230 
231     tokio::time::sleep_until(deadline).await;
232 
233     assert!(tokio::time::Instant::now() >= deadline);
234 }
235 
236 #[tokio::test]
long_sleeps()237 async fn long_sleeps() {
238     tokio::time::pause();
239 
240     let deadline = tokio::time::Instant::now()
241         + Duration::from_secs(
242             // about 10 years
243             10 * 365 * 24 * 3600,
244         );
245 
246     tokio::time::sleep_until(deadline).await;
247 
248     assert!(tokio::time::Instant::now() >= deadline);
249     assert!(tokio::time::Instant::now() <= deadline + Duration::from_millis(1));
250 }
251 
252 #[tokio::test]
253 #[should_panic(expected = "Duration too far into the future")]
very_long_sleeps()254 async fn very_long_sleeps() {
255     tokio::time::pause();
256 
257     // Some platforms (eg macos) can't represent times this far in the future
258     if let Some(deadline) = tokio::time::Instant::now().checked_add(Duration::from_secs(1u64 << 62))
259     {
260         tokio::time::sleep_until(deadline).await;
261     } else {
262         // make it pass anyway (we can't skip/ignore the test based on the
263         // result of checked_add)
264         panic!("Duration too far into the future (test ignored)")
265     }
266 }
267 
268 #[tokio::test]
reset_after_firing()269 async fn reset_after_firing() {
270     let timer = tokio::time::sleep(std::time::Duration::from_millis(1));
271     tokio::pin!(timer);
272 
273     let deadline = timer.deadline();
274 
275     timer.as_mut().await;
276     assert_ready!(timer
277         .as_mut()
278         .poll(&mut Context::from_waker(noop_waker_ref())));
279     timer
280         .as_mut()
281         .reset(tokio::time::Instant::now() + std::time::Duration::from_secs(600));
282 
283     assert_ne!(deadline, timer.deadline());
284 
285     assert_pending!(timer
286         .as_mut()
287         .poll(&mut Context::from_waker(noop_waker_ref())));
288     assert_pending!(timer
289         .as_mut()
290         .poll(&mut Context::from_waker(noop_waker_ref())));
291 }
292 
293 const NUM_LEVELS: usize = 6;
294 const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
295 
296 #[tokio::test]
exactly_max()297 async fn exactly_max() {
298     time::pause();
299     time::sleep(ms(MAX_DURATION)).await;
300 }
301 
302 #[tokio::test]
no_out_of_bounds_close_to_max()303 async fn no_out_of_bounds_close_to_max() {
304     time::pause();
305     time::sleep(ms(MAX_DURATION - 1)).await;
306 }
307 
ms(n: u64) -> Duration308 fn ms(n: u64) -> Duration {
309     Duration::from_millis(n)
310 }
311 
312 #[tokio::test]
drop_after_reschedule_at_new_scheduled_time()313 async fn drop_after_reschedule_at_new_scheduled_time() {
314     use futures::poll;
315 
316     tokio::time::pause();
317 
318     let start = tokio::time::Instant::now();
319 
320     let mut a = Box::pin(tokio::time::sleep(Duration::from_millis(5)));
321     let mut b = Box::pin(tokio::time::sleep(Duration::from_millis(5)));
322     let mut c = Box::pin(tokio::time::sleep(Duration::from_millis(10)));
323 
324     let _ = poll!(&mut a);
325     let _ = poll!(&mut b);
326     let _ = poll!(&mut c);
327 
328     b.as_mut().reset(start + Duration::from_millis(10));
329     a.await;
330 
331     drop(b);
332 }
333 
334 #[tokio::test]
drop_from_wake()335 async fn drop_from_wake() {
336     use std::future::Future;
337     use std::pin::Pin;
338     use std::sync::atomic::{AtomicBool, Ordering};
339     use std::sync::{Arc, Mutex};
340     use std::task::Context;
341 
342     let panicked = Arc::new(AtomicBool::new(false));
343     let list: Arc<Mutex<Vec<Pin<Box<tokio::time::Sleep>>>>> = Arc::new(Mutex::new(Vec::new()));
344 
345     let arc_wake = Arc::new(DropWaker(panicked.clone(), list.clone()));
346     let arc_wake = futures::task::waker(arc_wake);
347 
348     tokio::time::pause();
349 
350     let mut lock = list.lock().unwrap();
351 
352     for _ in 0..100 {
353         let mut timer = Box::pin(tokio::time::sleep(Duration::from_millis(10)));
354 
355         let _ = timer.as_mut().poll(&mut Context::from_waker(&arc_wake));
356 
357         lock.push(timer);
358     }
359 
360     drop(lock);
361 
362     tokio::time::sleep(Duration::from_millis(11)).await;
363 
364     assert!(
365         !panicked.load(Ordering::SeqCst),
366         "paniced when dropping timers"
367     );
368 
369     #[derive(Clone)]
370     struct DropWaker(
371         Arc<AtomicBool>,
372         Arc<Mutex<Vec<Pin<Box<tokio::time::Sleep>>>>>,
373     );
374 
375     impl futures::task::ArcWake for DropWaker {
376         fn wake_by_ref(arc_self: &Arc<Self>) {
377             let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
378                 *arc_self.1.lock().expect("panic in lock") = Vec::new()
379             }));
380 
381             if result.is_err() {
382                 arc_self.0.store(true, Ordering::SeqCst);
383             }
384         }
385     }
386 }
387