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 #[test]
172 #[should_panic]
creating_sleep_outside_of_context()173 fn creating_sleep_outside_of_context() {
174 let now = Instant::now();
175
176 // This creates a delay outside of the context of a mock timer. This tests
177 // that it will panic.
178 let _fut = time::sleep_until(now + ms(500));
179 }
180
181 #[tokio::test]
greater_than_max()182 async fn greater_than_max() {
183 const YR_5: u64 = 5 * 365 * 24 * 60 * 60 * 1000;
184
185 time::pause();
186 time::sleep_until(Instant::now() + ms(YR_5)).await;
187 }
188
189 #[tokio::test]
short_sleeps()190 async fn short_sleeps() {
191 for i in 0..10000 {
192 if (i % 10) == 0 {
193 eprintln!("=== {}", i);
194 }
195 tokio::time::sleep(std::time::Duration::from_millis(0)).await;
196 }
197 }
198
199 #[tokio::test]
multi_long_sleeps()200 async fn multi_long_sleeps() {
201 tokio::time::pause();
202
203 for _ in 0..5u32 {
204 tokio::time::sleep(Duration::from_secs(
205 // about a year
206 365 * 24 * 3600,
207 ))
208 .await;
209 }
210
211 let deadline = tokio::time::Instant::now()
212 + Duration::from_secs(
213 // about 10 years
214 10 * 365 * 24 * 3600,
215 );
216
217 tokio::time::sleep_until(deadline).await;
218
219 assert!(tokio::time::Instant::now() >= deadline);
220 }
221
222 #[tokio::test]
long_sleeps()223 async fn long_sleeps() {
224 tokio::time::pause();
225
226 let deadline = tokio::time::Instant::now()
227 + Duration::from_secs(
228 // about 10 years
229 10 * 365 * 24 * 3600,
230 );
231
232 tokio::time::sleep_until(deadline).await;
233
234 assert!(tokio::time::Instant::now() >= deadline);
235 assert!(tokio::time::Instant::now() <= deadline + Duration::from_millis(1));
236 }
237
238 #[tokio::test]
239 #[should_panic(expected = "Duration too far into the future")]
very_long_sleeps()240 async fn very_long_sleeps() {
241 tokio::time::pause();
242
243 // Some platforms (eg macos) can't represent times this far in the future
244 if let Some(deadline) = tokio::time::Instant::now().checked_add(Duration::from_secs(1u64 << 62))
245 {
246 tokio::time::sleep_until(deadline).await;
247 } else {
248 // make it pass anyway (we can't skip/ignore the test based on the
249 // result of checked_add)
250 panic!("Duration too far into the future (test ignored)")
251 }
252 }
253
254 #[tokio::test]
reset_after_firing()255 async fn reset_after_firing() {
256 let timer = tokio::time::sleep(std::time::Duration::from_millis(1));
257 tokio::pin!(timer);
258
259 let deadline = timer.deadline();
260
261 timer.as_mut().await;
262 assert_ready!(timer
263 .as_mut()
264 .poll(&mut Context::from_waker(noop_waker_ref())));
265 timer
266 .as_mut()
267 .reset(tokio::time::Instant::now() + std::time::Duration::from_secs(600));
268
269 assert_ne!(deadline, timer.deadline());
270
271 assert_pending!(timer
272 .as_mut()
273 .poll(&mut Context::from_waker(noop_waker_ref())));
274 assert_pending!(timer
275 .as_mut()
276 .poll(&mut Context::from_waker(noop_waker_ref())));
277 }
278
279 const NUM_LEVELS: usize = 6;
280 const MAX_DURATION: u64 = (1 << (6 * NUM_LEVELS)) - 1;
281
282 #[tokio::test]
exactly_max()283 async fn exactly_max() {
284 time::pause();
285 time::sleep(ms(MAX_DURATION)).await;
286 }
287
288 #[tokio::test]
no_out_of_bounds_close_to_max()289 async fn no_out_of_bounds_close_to_max() {
290 time::pause();
291 time::sleep(ms(MAX_DURATION - 1)).await;
292 }
293
ms(n: u64) -> Duration294 fn ms(n: u64) -> Duration {
295 Duration::from_millis(n)
296 }
297
298 #[tokio::test]
drop_after_reschedule_at_new_scheduled_time()299 async fn drop_after_reschedule_at_new_scheduled_time() {
300 use futures::poll;
301
302 tokio::time::pause();
303
304 let start = tokio::time::Instant::now();
305
306 let mut a = Box::pin(tokio::time::sleep(Duration::from_millis(5)));
307 let mut b = Box::pin(tokio::time::sleep(Duration::from_millis(5)));
308 let mut c = Box::pin(tokio::time::sleep(Duration::from_millis(10)));
309
310 let _ = poll!(&mut a);
311 let _ = poll!(&mut b);
312 let _ = poll!(&mut c);
313
314 b.as_mut().reset(start + Duration::from_millis(10));
315 a.await;
316
317 drop(b);
318 }
319
320 #[tokio::test]
drop_from_wake()321 async fn drop_from_wake() {
322 use std::future::Future;
323 use std::pin::Pin;
324 use std::sync::atomic::{AtomicBool, Ordering};
325 use std::sync::{Arc, Mutex};
326 use std::task::Context;
327
328 let panicked = Arc::new(AtomicBool::new(false));
329 let list: Arc<Mutex<Vec<Pin<Box<tokio::time::Sleep>>>>> = Arc::new(Mutex::new(Vec::new()));
330
331 let arc_wake = Arc::new(DropWaker(panicked.clone(), list.clone()));
332 let arc_wake = futures::task::waker(arc_wake);
333
334 tokio::time::pause();
335
336 let mut lock = list.lock().unwrap();
337
338 for _ in 0..100 {
339 let mut timer = Box::pin(tokio::time::sleep(Duration::from_millis(10)));
340
341 let _ = timer.as_mut().poll(&mut Context::from_waker(&arc_wake));
342
343 lock.push(timer);
344 }
345
346 drop(lock);
347
348 tokio::time::sleep(Duration::from_millis(11)).await;
349
350 assert!(
351 !panicked.load(Ordering::SeqCst),
352 "panicked when dropping timers"
353 );
354
355 #[derive(Clone)]
356 struct DropWaker(
357 Arc<AtomicBool>,
358 Arc<Mutex<Vec<Pin<Box<tokio::time::Sleep>>>>>,
359 );
360
361 impl futures::task::ArcWake for DropWaker {
362 fn wake_by_ref(arc_self: &Arc<Self>) {
363 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
364 *arc_self.1.lock().expect("panic in lock") = Vec::new()
365 }));
366
367 if result.is_err() {
368 arc_self.0.store(true, Ordering::SeqCst);
369 }
370 }
371 }
372 }
373