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