1 #![recursion_limit="128"]
2 
3 use futures::{pending, pin_mut, poll, join, try_join, select};
4 use futures::channel::{mpsc, oneshot};
5 use futures::executor::block_on;
6 use futures::future::{self, FutureExt, poll_fn};
7 use futures::sink::SinkExt;
8 use futures::stream::StreamExt;
9 use futures::task::{Context, Poll};
10 
11 #[test]
poll_and_pending()12 fn poll_and_pending() {
13     let pending_once = async { pending!() };
14     block_on(async {
15         pin_mut!(pending_once);
16         assert_eq!(Poll::Pending, poll!(&mut pending_once));
17         assert_eq!(Poll::Ready(()), poll!(&mut pending_once));
18     });
19 }
20 
21 #[test]
join()22 fn join() {
23     let (tx1, rx1) = oneshot::channel::<i32>();
24     let (tx2, rx2) = oneshot::channel::<i32>();
25 
26     let fut = async {
27         let res = join!(rx1, rx2);
28         assert_eq!((Ok(1), Ok(2)), res);
29     };
30 
31     block_on(async {
32         pin_mut!(fut);
33         assert_eq!(Poll::Pending, poll!(&mut fut));
34         tx1.send(1).unwrap();
35         assert_eq!(Poll::Pending, poll!(&mut fut));
36         tx2.send(2).unwrap();
37         assert_eq!(Poll::Ready(()), poll!(&mut fut));
38     });
39 }
40 
41 #[test]
select()42 fn select() {
43     let (tx1, rx1) = oneshot::channel::<i32>();
44     let (_tx2, rx2) = oneshot::channel::<i32>();
45     tx1.send(1).unwrap();
46     let mut ran = false;
47     block_on(async {
48         select! {
49             res = rx1.fuse() => {
50                 assert_eq!(Ok(1), res);
51                 ran = true;
52             },
53             _ = rx2.fuse() => unreachable!(),
54         }
55     });
56     assert!(ran);
57 }
58 
59 #[test]
select_biased()60 fn select_biased() {
61     use futures::select_biased;
62 
63     let (tx1, rx1) = oneshot::channel::<i32>();
64     let (_tx2, rx2) = oneshot::channel::<i32>();
65     tx1.send(1).unwrap();
66     let mut ran = false;
67     block_on(async {
68         select_biased! {
69             res = rx1.fuse() => {
70                 assert_eq!(Ok(1), res);
71                 ran = true;
72             },
73             _ = rx2.fuse() => unreachable!(),
74         }
75     });
76     assert!(ran);
77 }
78 
79 #[test]
select_streams()80 fn select_streams() {
81     let (mut tx1, rx1) = mpsc::channel::<i32>(1);
82     let (mut tx2, rx2) = mpsc::channel::<i32>(1);
83     let mut rx1 = rx1.fuse();
84     let mut rx2 = rx2.fuse();
85     let mut ran = false;
86     let mut total = 0;
87     block_on(async {
88         let mut tx1_opt;
89         let mut tx2_opt;
90         select! {
91             _ = rx1.next() => panic!(),
92             _ = rx2.next() => panic!(),
93             default => {
94                 tx1.send(2).await.unwrap();
95                 tx2.send(3).await.unwrap();
96                 tx1_opt = Some(tx1);
97                 tx2_opt = Some(tx2);
98             }
99             complete => panic!(),
100         }
101         loop {
102             select! {
103                 // runs first and again after default
104                 x = rx1.next() => if let Some(x) = x { total += x; },
105                 // runs second and again after default
106                 x = rx2.next()  => if let Some(x) = x { total += x; },
107                 // runs third
108                 default => {
109                     assert_eq!(total, 5);
110                     ran = true;
111                     drop(tx1_opt.take().unwrap());
112                     drop(tx2_opt.take().unwrap());
113                 },
114                 // runs last
115                 complete => break,
116             };
117         }
118     });
119     assert!(ran);
120 }
121 
122 #[test]
select_can_move_uncompleted_futures()123 fn select_can_move_uncompleted_futures() {
124     let (tx1, rx1) = oneshot::channel::<i32>();
125     let (tx2, rx2) = oneshot::channel::<i32>();
126     tx1.send(1).unwrap();
127     tx2.send(2).unwrap();
128     let mut ran = false;
129     let mut rx1 = rx1.fuse();
130     let mut rx2 = rx2.fuse();
131     block_on(async {
132         select! {
133             res = rx1 => {
134                 assert_eq!(Ok(1), res);
135                 assert_eq!(Ok(2), rx2.await);
136                 ran = true;
137             },
138             res = rx2 => {
139                 assert_eq!(Ok(2), res);
140                 assert_eq!(Ok(1), rx1.await);
141                 ran = true;
142             },
143         }
144     });
145     assert!(ran);
146 }
147 
148 #[test]
select_nested()149 fn select_nested() {
150     let mut outer_fut = future::ready(1);
151     let mut inner_fut = future::ready(2);
152     let res = block_on(async {
153         select! {
154             x = outer_fut => {
155                 select! {
156                     y = inner_fut => x + y,
157                 }
158             }
159         }
160     });
161     assert_eq!(res, 3);
162 }
163 
164 #[test]
select_size()165 fn select_size() {
166     let fut = async {
167         let mut ready = future::ready(0i32);
168         select! {
169             _ = ready => {},
170         }
171     };
172     assert_eq!(::std::mem::size_of_val(&fut), 24);
173 
174     let fut = async {
175         let mut ready1 = future::ready(0i32);
176         let mut ready2 = future::ready(0i32);
177         select! {
178             _ = ready1 => {},
179             _ = ready2 => {},
180         }
181     };
182     assert_eq!(::std::mem::size_of_val(&fut), 40);
183 }
184 
185 #[test]
select_on_non_unpin_expressions()186 fn select_on_non_unpin_expressions() {
187     // The returned Future is !Unpin
188     let make_non_unpin_fut = || { async {
189         5
190     }};
191 
192     let res = block_on(async {
193         let select_res;
194         select! {
195             value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
196             value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
197         };
198         select_res
199     });
200     assert_eq!(res, 5);
201 }
202 
203 #[test]
select_on_non_unpin_expressions_with_default()204 fn select_on_non_unpin_expressions_with_default() {
205     // The returned Future is !Unpin
206     let make_non_unpin_fut = || { async {
207         5
208     }};
209 
210     let res = block_on(async {
211         let select_res;
212         select! {
213             value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
214             value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
215             default => { select_res = 7 },
216         };
217         select_res
218     });
219     assert_eq!(res, 5);
220 }
221 
222 #[test]
select_on_non_unpin_size()223 fn select_on_non_unpin_size() {
224     // The returned Future is !Unpin
225     let make_non_unpin_fut = || { async {
226         5
227     }};
228 
229     let fut = async {
230         let select_res;
231         select! {
232             value_1 = make_non_unpin_fut().fuse() => { select_res = value_1 },
233             value_2 = make_non_unpin_fut().fuse() => { select_res = value_2 },
234         };
235         select_res
236     };
237 
238     assert_eq!(48, std::mem::size_of_val(&fut));
239 }
240 
241 #[test]
select_can_be_used_as_expression()242 fn select_can_be_used_as_expression() {
243     block_on(async {
244         let res = select! {
245             x = future::ready(7) => { x },
246             y = future::ready(3) => { y + 1 },
247         };
248         assert!(res == 7 || res == 4);
249     });
250 }
251 
252 #[test]
select_with_default_can_be_used_as_expression()253 fn select_with_default_can_be_used_as_expression() {
254     fn poll_always_pending<T>(_cx: &mut Context<'_>) -> Poll<T> {
255         Poll::Pending
256     }
257 
258     block_on(async {
259         let res = select! {
260             x = poll_fn(poll_always_pending::<i32>).fuse() => x,
261             y = poll_fn(poll_always_pending::<i32>).fuse() => { y + 1 },
262             default => 99,
263         };
264         assert_eq!(res, 99);
265     });
266 }
267 
268 #[test]
select_with_complete_can_be_used_as_expression()269 fn select_with_complete_can_be_used_as_expression() {
270     block_on(async {
271         let res = select! {
272             x = future::pending::<i32>() => { x },
273             y = future::pending::<i32>() => { y + 1 },
274             default => 99,
275             complete => 237,
276         };
277         assert_eq!(res, 237);
278     });
279 }
280 
require_mutable(_: &mut i32)281 async fn require_mutable(_: &mut i32) {}
async_noop()282 async fn async_noop() {}
283 
284 #[test]
select_on_mutable_borrowing_future_with_same_borrow_in_block()285 fn select_on_mutable_borrowing_future_with_same_borrow_in_block() {
286     block_on(async {
287         let mut value = 234;
288         select! {
289             x = require_mutable(&mut value).fuse() => { },
290             y = async_noop().fuse() => {
291                 value += 5;
292             },
293         }
294     });
295 }
296 
297 #[test]
select_on_mutable_borrowing_future_with_same_borrow_in_block_and_default()298 fn select_on_mutable_borrowing_future_with_same_borrow_in_block_and_default() {
299     block_on(async {
300         let mut value = 234;
301         select! {
302             x = require_mutable(&mut value).fuse() => { },
303             y = async_noop().fuse() => {
304                 value += 5;
305             },
306             default => {
307                 value += 27;
308             },
309         }
310     });
311 }
312 
313 #[test]
join_size()314 fn join_size() {
315     let fut = async {
316         let ready = future::ready(0i32);
317         join!(ready)
318     };
319     assert_eq!(::std::mem::size_of_val(&fut), 16);
320 
321     let fut = async {
322         let ready1 = future::ready(0i32);
323         let ready2 = future::ready(0i32);
324         join!(ready1, ready2)
325     };
326     assert_eq!(::std::mem::size_of_val(&fut), 28);
327 }
328 
329 #[test]
try_join_size()330 fn try_join_size() {
331     let fut = async {
332         let ready = future::ready(Ok::<i32, i32>(0));
333         try_join!(ready)
334     };
335     assert_eq!(::std::mem::size_of_val(&fut), 16);
336 
337     let fut = async {
338         let ready1 = future::ready(Ok::<i32, i32>(0));
339         let ready2 = future::ready(Ok::<i32, i32>(0));
340         try_join!(ready1, ready2)
341     };
342     assert_eq!(::std::mem::size_of_val(&fut), 28);
343 }
344 
345 #[test]
join_doesnt_require_unpin()346 fn join_doesnt_require_unpin() {
347     let _ = async {
348         join!(async {}, async {})
349     };
350 }
351 
352 #[test]
try_join_doesnt_require_unpin()353 fn try_join_doesnt_require_unpin() {
354     let _ = async {
355         try_join!(
356             async { Ok::<(), ()>(()) },
357             async { Ok::<(), ()>(()) },
358         )
359     };
360 }
361