1 use futures::executor::block_on;
2 use futures::future::{self, FusedFuture, FutureExt};
3 use futures::select;
4 use futures::stream::{FuturesUnordered, StreamExt};
5 use futures::task::{Context, Poll};
6 use futures_test::future::FutureTestExt;
7 use futures_test::task::new_count_waker;
8 
9 #[test]
is_terminated()10 fn is_terminated() {
11     let (waker, counter) = new_count_waker();
12     let mut cx = Context::from_waker(&waker);
13 
14     let mut tasks = FuturesUnordered::new();
15 
16     let mut select_next_some = tasks.select_next_some();
17     assert_eq!(select_next_some.is_terminated(), false);
18     assert_eq!(select_next_some.poll_unpin(&mut cx), Poll::Pending);
19     assert_eq!(counter, 1);
20     assert_eq!(select_next_some.is_terminated(), true);
21     drop(select_next_some);
22 
23     tasks.push(future::ready(1));
24 
25     let mut select_next_some = tasks.select_next_some();
26     assert_eq!(select_next_some.is_terminated(), false);
27     assert_eq!(select_next_some.poll_unpin(&mut cx), Poll::Ready(1));
28     assert_eq!(select_next_some.is_terminated(), false);
29     assert_eq!(select_next_some.poll_unpin(&mut cx), Poll::Pending);
30     assert_eq!(select_next_some.is_terminated(), true);
31 }
32 
33 #[test]
select()34 fn select() {
35     // Checks that even though `async_tasks` will yield a `None` and return
36     // `is_terminated() == true` during the first poll, it manages to toggle
37     // back to having items after a future is pushed into it during the second
38     // poll (after pending_once completes).
39     block_on(async {
40         let mut fut = future::ready(1).pending_once();
41         let mut async_tasks = FuturesUnordered::new();
42         let mut total = 0;
43         loop {
44             select! {
45                 num = fut => {
46                     total += num;
47                     async_tasks.push(async { 5 });
48                 },
49                 num = async_tasks.select_next_some() => {
50                     total += num;
51                 }
52                 complete => break,
53             }
54         }
55         assert_eq!(total, 6);
56     });
57 }
58 
59 // Check that `select!` macro does not fail when importing from `futures_util`.
60 #[test]
futures_util_select()61 fn futures_util_select() {
62     use futures_util::select;
63 
64     // Checks that even though `async_tasks` will yield a `None` and return
65     // `is_terminated() == true` during the first poll, it manages to toggle
66     // back to having items after a future is pushed into it during the second
67     // poll (after pending_once completes).
68     block_on(async {
69         let mut fut = future::ready(1).pending_once();
70         let mut async_tasks = FuturesUnordered::new();
71         let mut total = 0;
72         loop {
73             select! {
74                 num = fut => {
75                     total += num;
76                     async_tasks.push(async { 5 });
77                 },
78                 num = async_tasks.select_next_some() => {
79                     total += num;
80                 }
81                 complete => break,
82             }
83         }
84         assert_eq!(total, 6);
85     });
86 }
87