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