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