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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
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 ] |
191 | async 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 ] |
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 ] |
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 ] |
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 ] |
265 | async fn exactly_max() { |
266 | time::pause(); |
267 | time::sleep(ms(MAX_DURATION)).await; |
268 | } |
269 | |
270 | #[tokio::test ] |
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 ] |
285 | async fn no_out_of_bounds_close_to_max() { |
286 | time::pause(); |
287 | time::sleep(ms(MAX_DURATION - 1)).await; |
288 | } |
289 | |
290 | fn ms(n: u64) -> Duration { |
291 | Duration::from_millis(n) |
292 | } |
293 | |
294 | #[tokio::test ] |
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 ] |
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 | |