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