1 | #![warn (rust_2018_idioms)] |
2 | #![cfg (feature = "full" )] |
3 | |
4 | use rand::SeedableRng; |
5 | use rand::{rngs::StdRng, Rng}; |
6 | use tokio::time::{self, Duration, Instant, Sleep}; |
7 | use tokio_test::{assert_elapsed, assert_pending, assert_ready, assert_ready_eq, task}; |
8 | |
9 | #[cfg (not(target_os = "wasi" ))] |
10 | use tokio_test::assert_err; |
11 | |
12 | use std::{ |
13 | future::Future, |
14 | pin::Pin, |
15 | task::{Context, Poll}, |
16 | }; |
17 | |
18 | #[tokio::test ] |
19 | async fn pause_time_in_main() { |
20 | tokio::time::pause(); |
21 | } |
22 | |
23 | #[tokio::test ] |
24 | async fn pause_time_in_task() { |
25 | let t = tokio::spawn(async { |
26 | tokio::time::pause(); |
27 | }); |
28 | |
29 | t.await.unwrap(); |
30 | } |
31 | |
32 | #[cfg (all(feature = "full" , not(target_os = "wasi" )))] // Wasi doesn't support threads |
33 | #[tokio::test (flavor = "multi_thread" , worker_threads = 1)] |
34 | #[should_panic ] |
35 | async fn pause_time_in_main_threads() { |
36 | tokio::time::pause(); |
37 | } |
38 | |
39 | #[cfg (panic = "unwind" )] |
40 | #[cfg (all(feature = "full" , not(target_os = "wasi" )))] // Wasi doesn't support threads |
41 | #[tokio::test (flavor = "multi_thread" , worker_threads = 1)] |
42 | async fn pause_time_in_spawn_threads() { |
43 | let t = tokio::spawn(async { |
44 | tokio::time::pause(); |
45 | }); |
46 | |
47 | assert_err!(t.await); |
48 | } |
49 | |
50 | #[test] |
51 | fn paused_time_is_deterministic() { |
52 | let run_1 = paused_time_stress_run(); |
53 | let run_2 = paused_time_stress_run(); |
54 | |
55 | assert_eq!(run_1, run_2); |
56 | } |
57 | |
58 | #[tokio::main(flavor = "current_thread" , start_paused = true)] |
59 | async fn paused_time_stress_run() -> Vec<Duration> { |
60 | let mut rng = StdRng::seed_from_u64(1); |
61 | |
62 | let mut times = vec![]; |
63 | let start = Instant::now(); |
64 | for _ in 0..10_000 { |
65 | let sleep = rng.gen_range(Duration::from_secs(0)..Duration::from_secs(1)); |
66 | time::sleep(sleep).await; |
67 | times.push(start.elapsed()); |
68 | } |
69 | |
70 | times |
71 | } |
72 | |
73 | #[tokio::test (start_paused = true)] |
74 | async fn advance_after_poll() { |
75 | time::sleep(ms(1)).await; |
76 | |
77 | let start = Instant::now(); |
78 | |
79 | let mut sleep = task::spawn(time::sleep_until(start + ms(300))); |
80 | |
81 | assert_pending!(sleep.poll()); |
82 | |
83 | let before = Instant::now(); |
84 | time::advance(ms(100)).await; |
85 | assert_elapsed!(before, ms(100)); |
86 | |
87 | assert_pending!(sleep.poll()); |
88 | } |
89 | |
90 | #[tokio::test (start_paused = true)] |
91 | async fn sleep_no_poll() { |
92 | let start = Instant::now(); |
93 | |
94 | // TODO: Skip this |
95 | time::advance(ms(1)).await; |
96 | |
97 | let mut sleep = task::spawn(time::sleep_until(start + ms(300))); |
98 | |
99 | let before = Instant::now(); |
100 | time::advance(ms(100)).await; |
101 | assert_elapsed!(before, ms(100)); |
102 | |
103 | assert_pending!(sleep.poll()); |
104 | } |
105 | |
106 | enum State { |
107 | Begin, |
108 | AwaitingAdvance(Pin<Box<dyn Future<Output = ()>>>), |
109 | AfterAdvance, |
110 | } |
111 | |
112 | struct Tester { |
113 | sleep: Pin<Box<Sleep>>, |
114 | state: State, |
115 | before: Option<Instant>, |
116 | poll: bool, |
117 | } |
118 | |
119 | impl Future for Tester { |
120 | type Output = (); |
121 | |
122 | fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
123 | match &mut self.state { |
124 | State::Begin => { |
125 | if self.poll { |
126 | assert_pending!(self.sleep.as_mut().poll(cx)); |
127 | } |
128 | self.before = Some(Instant::now()); |
129 | let advance_fut = Box::pin(time::advance(ms(100))); |
130 | self.state = State::AwaitingAdvance(advance_fut); |
131 | self.poll(cx) |
132 | } |
133 | State::AwaitingAdvance(ref mut advance_fut) => match advance_fut.as_mut().poll(cx) { |
134 | Poll::Pending => Poll::Pending, |
135 | Poll::Ready(()) => { |
136 | self.state = State::AfterAdvance; |
137 | self.poll(cx) |
138 | } |
139 | }, |
140 | State::AfterAdvance => { |
141 | assert_elapsed!(self.before.unwrap(), ms(100)); |
142 | |
143 | assert_pending!(self.sleep.as_mut().poll(cx)); |
144 | |
145 | Poll::Ready(()) |
146 | } |
147 | } |
148 | } |
149 | } |
150 | |
151 | #[tokio::test (start_paused = true)] |
152 | async fn sleep_same_task() { |
153 | let start = Instant::now(); |
154 | |
155 | // TODO: Skip this |
156 | time::advance(ms(1)).await; |
157 | |
158 | let sleep = Box::pin(time::sleep_until(start + ms(300))); |
159 | |
160 | Tester { |
161 | sleep, |
162 | state: State::Begin, |
163 | before: None, |
164 | poll: true, |
165 | } |
166 | .await; |
167 | } |
168 | |
169 | #[tokio::test (start_paused = true)] |
170 | async fn sleep_same_task_no_poll() { |
171 | let start = Instant::now(); |
172 | |
173 | // TODO: Skip this |
174 | time::advance(ms(1)).await; |
175 | |
176 | let sleep = Box::pin(time::sleep_until(start + ms(300))); |
177 | |
178 | Tester { |
179 | sleep, |
180 | state: State::Begin, |
181 | before: None, |
182 | poll: false, |
183 | } |
184 | .await; |
185 | } |
186 | |
187 | #[tokio::test (start_paused = true)] |
188 | async fn interval() { |
189 | let start = Instant::now(); |
190 | |
191 | // TODO: Skip this |
192 | time::advance(ms(1)).await; |
193 | |
194 | let mut i = task::spawn(time::interval_at(start, ms(300))); |
195 | |
196 | assert_ready_eq!(poll_next(&mut i), start); |
197 | assert_pending!(poll_next(&mut i)); |
198 | |
199 | let before = Instant::now(); |
200 | time::advance(ms(100)).await; |
201 | assert_elapsed!(before, ms(100)); |
202 | assert_pending!(poll_next(&mut i)); |
203 | |
204 | let before = Instant::now(); |
205 | time::advance(ms(200)).await; |
206 | assert_elapsed!(before, ms(200)); |
207 | assert_ready_eq!(poll_next(&mut i), start + ms(300)); |
208 | assert_pending!(poll_next(&mut i)); |
209 | |
210 | let before = Instant::now(); |
211 | time::advance(ms(400)).await; |
212 | assert_elapsed!(before, ms(400)); |
213 | assert_ready_eq!(poll_next(&mut i), start + ms(600)); |
214 | assert_pending!(poll_next(&mut i)); |
215 | |
216 | let before = Instant::now(); |
217 | time::advance(ms(500)).await; |
218 | assert_elapsed!(before, ms(500)); |
219 | assert_ready_eq!(poll_next(&mut i), start + ms(900)); |
220 | assert_ready_eq!(poll_next(&mut i), start + ms(1200)); |
221 | assert_pending!(poll_next(&mut i)); |
222 | } |
223 | |
224 | #[tokio::test (start_paused = true)] |
225 | async fn test_time_advance_sub_ms() { |
226 | let now = Instant::now(); |
227 | |
228 | let dur = Duration::from_micros(51_592); |
229 | time::advance(dur).await; |
230 | |
231 | assert_eq!(now.elapsed(), dur); |
232 | |
233 | let now = Instant::now(); |
234 | let dur = Duration::from_micros(1); |
235 | time::advance(dur).await; |
236 | |
237 | assert_eq!(now.elapsed(), dur); |
238 | } |
239 | |
240 | #[tokio::test (start_paused = true)] |
241 | async fn test_time_advance_3ms_and_change() { |
242 | let now = Instant::now(); |
243 | |
244 | let dur = Duration::from_micros(3_141_592); |
245 | time::advance(dur).await; |
246 | |
247 | assert_eq!(now.elapsed(), dur); |
248 | |
249 | let now = Instant::now(); |
250 | let dur = Duration::from_micros(3_123_456); |
251 | time::advance(dur).await; |
252 | |
253 | assert_eq!(now.elapsed(), dur); |
254 | } |
255 | |
256 | #[tokio::test (start_paused = true)] |
257 | async fn regression_3710_with_submillis_advance() { |
258 | let start = Instant::now(); |
259 | |
260 | time::advance(Duration::from_millis(1)).await; |
261 | |
262 | let mut sleep = task::spawn(time::sleep_until(start + Duration::from_secs(60))); |
263 | |
264 | assert_pending!(sleep.poll()); |
265 | |
266 | let before = Instant::now(); |
267 | let dur = Duration::from_micros(51_592); |
268 | time::advance(dur).await; |
269 | assert_eq!(before.elapsed(), dur); |
270 | |
271 | assert_pending!(sleep.poll()); |
272 | } |
273 | |
274 | #[tokio::test (start_paused = true)] |
275 | async fn exact_1ms_advance() { |
276 | let now = Instant::now(); |
277 | |
278 | let dur = Duration::from_millis(1); |
279 | time::advance(dur).await; |
280 | |
281 | assert_eq!(now.elapsed(), dur); |
282 | |
283 | let now = Instant::now(); |
284 | let dur = Duration::from_millis(1); |
285 | time::advance(dur).await; |
286 | |
287 | assert_eq!(now.elapsed(), dur); |
288 | } |
289 | |
290 | #[tokio::test (start_paused = true)] |
291 | async fn advance_once_with_timer() { |
292 | let mut sleep = task::spawn(time::sleep(Duration::from_millis(1))); |
293 | assert_pending!(sleep.poll()); |
294 | |
295 | time::advance(Duration::from_micros(250)).await; |
296 | assert_pending!(sleep.poll()); |
297 | |
298 | time::advance(Duration::from_micros(1500)).await; |
299 | |
300 | assert!(sleep.is_woken()); |
301 | assert_ready!(sleep.poll()); |
302 | } |
303 | |
304 | #[tokio::test (start_paused = true)] |
305 | async fn advance_multi_with_timer() { |
306 | // Round to the nearest ms |
307 | // time::sleep(Duration::from_millis(1)).await; |
308 | |
309 | let mut sleep = task::spawn(time::sleep(Duration::from_millis(1))); |
310 | assert_pending!(sleep.poll()); |
311 | |
312 | time::advance(Duration::from_micros(250)).await; |
313 | assert_pending!(sleep.poll()); |
314 | |
315 | time::advance(Duration::from_micros(250)).await; |
316 | assert_pending!(sleep.poll()); |
317 | |
318 | time::advance(Duration::from_micros(250)).await; |
319 | assert_pending!(sleep.poll()); |
320 | |
321 | time::advance(Duration::from_micros(250)).await; |
322 | assert!(sleep.is_woken()); |
323 | assert_ready!(sleep.poll()); |
324 | } |
325 | |
326 | fn poll_next(interval: &mut task::Spawn<time::Interval>) -> Poll<Instant> { |
327 | interval.enter(|cx, mut interval| interval.poll_tick(cx)) |
328 | } |
329 | |
330 | fn ms(n: u64) -> Duration { |
331 | Duration::from_millis(n) |
332 | } |
333 | |