1#![warn(rust_2018_idioms)]
2#![cfg(feature = "full")]
3
4use std::future::Future;
5use std::task::Context;
6
7use futures::task::noop_waker_ref;
8
9use tokio::time::{self, Duration, Instant};
10use tokio_test::{assert_elapsed, assert_pending, assert_ready, task};
11
12#[tokio::test]
13async 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]
24async 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]
43async 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]
57async 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]
71async 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]
83async 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]
100async 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]
117async 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]
136async 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]
151async 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]
174fn 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]
183async 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]
191async fn short_sleeps() {
192 for _ in 0..1000 {
193 tokio::time::sleep(std::time::Duration::from_millis(0)).await;
194 }
195}
196
197#[tokio::test]
198async 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]
221async 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]
237async 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
261const NUM_LEVELS: usize = 6;
262const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
263
264#[tokio::test]
265async fn exactly_max() {
266 time::pause();
267 time::sleep(ms(MAX_DURATION)).await;
268}
269
270#[tokio::test]
271async 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]
285async fn no_out_of_bounds_close_to_max() {
286 time::pause();
287 time::sleep(ms(MAX_DURATION - 1)).await;
288}
289
290fn ms(n: u64) -> Duration {
291 Duration::from_millis(n)
292}
293
294#[tokio::test]
295async 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]
317async 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