1 #![warn(rust_2018_idioms)]
2 #![cfg(feature = "full")]
3 
4 use tokio::sync::oneshot;
5 use tokio::time::{self, timeout, timeout_at, Instant};
6 use tokio_test::*;
7 
8 use futures::future::pending;
9 use std::time::Duration;
10 
11 #[tokio::test]
simultaneous_deadline_future_completion()12 async fn simultaneous_deadline_future_completion() {
13     // Create a future that is immediately ready
14     let mut fut = task::spawn(timeout_at(Instant::now(), async {}));
15 
16     // Ready!
17     assert_ready_ok!(fut.poll());
18 }
19 
20 #[cfg_attr(target_os = "wasi", ignore = "FIXME: `fut.poll()` panics on Wasi")]
21 #[tokio::test]
completed_future_past_deadline()22 async fn completed_future_past_deadline() {
23     // Wrap it with a deadline
24     let mut fut = task::spawn(timeout_at(Instant::now() - ms(1000), async {}));
25 
26     // Ready!
27     assert_ready_ok!(fut.poll());
28 }
29 
30 #[tokio::test]
future_and_deadline_in_future()31 async fn future_and_deadline_in_future() {
32     time::pause();
33 
34     // Not yet complete
35     let (tx, rx) = oneshot::channel();
36 
37     // Wrap it with a deadline
38     let mut fut = task::spawn(timeout_at(Instant::now() + ms(100), rx));
39 
40     assert_pending!(fut.poll());
41 
42     // Turn the timer, it runs for the elapsed time
43     time::advance(ms(90)).await;
44 
45     assert_pending!(fut.poll());
46 
47     // Complete the future
48     tx.send(()).unwrap();
49     assert!(fut.is_woken());
50 
51     assert_ready_ok!(fut.poll()).unwrap();
52 }
53 
54 #[tokio::test]
future_and_timeout_in_future()55 async fn future_and_timeout_in_future() {
56     time::pause();
57 
58     // Not yet complete
59     let (tx, rx) = oneshot::channel();
60 
61     // Wrap it with a deadline
62     let mut fut = task::spawn(timeout(ms(100), rx));
63 
64     // Ready!
65     assert_pending!(fut.poll());
66 
67     // Turn the timer, it runs for the elapsed time
68     time::advance(ms(90)).await;
69 
70     assert_pending!(fut.poll());
71 
72     // Complete the future
73     tx.send(()).unwrap();
74 
75     assert_ready_ok!(fut.poll()).unwrap();
76 }
77 
78 #[tokio::test]
very_large_timeout()79 async fn very_large_timeout() {
80     time::pause();
81 
82     // Not yet complete
83     let (tx, rx) = oneshot::channel();
84 
85     // copy-paste unstable `Duration::MAX`
86     let duration_max = Duration::from_secs(u64::MAX) + Duration::from_nanos(999_999_999);
87 
88     // Wrap it with a deadline
89     let mut fut = task::spawn(timeout(duration_max, rx));
90 
91     // Ready!
92     assert_pending!(fut.poll());
93 
94     // Turn the timer, it runs for the elapsed time
95     time::advance(Duration::from_secs(86400 * 365 * 10)).await;
96 
97     assert_pending!(fut.poll());
98 
99     // Complete the future
100     tx.send(()).unwrap();
101 
102     assert_ready_ok!(fut.poll()).unwrap();
103 }
104 
105 #[tokio::test]
deadline_now_elapses()106 async fn deadline_now_elapses() {
107     use futures::future::pending;
108 
109     time::pause();
110 
111     // Wrap it with a deadline
112     let mut fut = task::spawn(timeout_at(Instant::now(), pending::<()>()));
113 
114     // Factor in jitter
115     // TODO: don't require this
116     time::advance(ms(1)).await;
117 
118     assert_ready_err!(fut.poll());
119 }
120 
121 #[tokio::test]
deadline_future_elapses()122 async fn deadline_future_elapses() {
123     time::pause();
124 
125     // Wrap it with a deadline
126     let mut fut = task::spawn(timeout_at(Instant::now() + ms(300), pending::<()>()));
127 
128     assert_pending!(fut.poll());
129 
130     time::advance(ms(301)).await;
131 
132     assert!(fut.is_woken());
133     assert_ready_err!(fut.poll());
134 }
135 
ms(n: u64) -> Duration136 fn ms(n: u64) -> Duration {
137     Duration::from_millis(n)
138 }
139 
140 #[tokio::test]
timeout_is_not_exhausted_by_future()141 async fn timeout_is_not_exhausted_by_future() {
142     let fut = timeout(ms(1), async {
143         let mut buffer = [0u8; 1];
144         loop {
145             use tokio::io::AsyncReadExt;
146             let _ = tokio::io::empty().read(&mut buffer).await;
147         }
148     });
149 
150     assert!(fut.await.is_err());
151 }
152