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