]> git.lizzy.rs Git - rust.git/blob - library/core/tests/future.rs
Rollup merge of #106714 - Ezrashaw:remove-e0490, r=davidtwco
[rust.git] / library / core / tests / future.rs
1 use std::future::{join, Future};
2 use std::pin::Pin;
3 use std::sync::Arc;
4 use std::task::{Context, Poll, Wake};
5 use std::thread;
6
7 struct PollN {
8     val: usize,
9     polled: usize,
10     num: usize,
11 }
12
13 impl Future for PollN {
14     type Output = usize;
15
16     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
17         self.polled += 1;
18
19         if self.polled == self.num {
20             return Poll::Ready(self.val);
21         }
22
23         cx.waker().wake_by_ref();
24         Poll::Pending
25     }
26 }
27
28 fn poll_n(val: usize, num: usize) -> PollN {
29     PollN { val, num, polled: 0 }
30 }
31
32 #[test]
33 #[cfg_attr(miri, ignore)] // self-referential generators do not work with Miri's aliasing checks
34 fn test_join() {
35     block_on(async move {
36         let x = join!(async { 0 }).await;
37         assert_eq!(x, 0);
38
39         let x = join!(async { 0 }, async { 1 }).await;
40         assert_eq!(x, (0, 1));
41
42         let x = join!(async { 0 }, async { 1 }, async { 2 }).await;
43         assert_eq!(x, (0, 1, 2));
44
45         let x = join!(
46             poll_n(0, 1),
47             poll_n(1, 5),
48             poll_n(2, 2),
49             poll_n(3, 1),
50             poll_n(4, 2),
51             poll_n(5, 3),
52             poll_n(6, 4),
53             poll_n(7, 1)
54         )
55         .await;
56         assert_eq!(x, (0, 1, 2, 3, 4, 5, 6, 7));
57
58         let y = String::new();
59         let x = join!(async {
60             println!("{}", &y);
61             1
62         })
63         .await;
64         assert_eq!(x, 1);
65     });
66 }
67
68 /// Tests that `join!(…)` behaves "like a function": evaluating its arguments
69 /// before applying any of its own logic.
70 ///
71 /// _e.g._, `join!(async_fn(&borrowed), …)` does not consume `borrowed`;
72 /// and `join!(opt_fut?, …)` does let that `?` refer to the callsite scope.
73 mod test_join_function_like_value_arg_semantics {
74     use super::*;
75
76     async fn async_fn(_: impl Sized) {}
77
78     // no need to _run_ this test, just to compile it.
79     fn _join_does_not_unnecessarily_move_mentioned_bindings() {
80         let not_copy = vec![()];
81         let _ = join!(async_fn(&not_copy)); // should not move `not_copy`
82         let _ = &not_copy; // OK
83     }
84
85     #[test]
86     fn join_lets_control_flow_effects_such_as_try_flow_through() {
87         let maybe_fut = None;
88         if false {
89             *&mut { maybe_fut } = Some(async {});
90             loop {}
91         }
92         assert!(Option::is_none(&try { join!(maybe_fut?, async { unreachable!() }) }));
93     }
94
95     #[test]
96     fn join_is_able_to_handle_temporaries() {
97         let _ = join!(async_fn(&String::from("temporary")));
98         let () = block_on(join!(async_fn(&String::from("temporary"))));
99     }
100 }
101
102 fn block_on(fut: impl Future) {
103     struct Waker;
104     impl Wake for Waker {
105         fn wake(self: Arc<Self>) {
106             thread::current().unpark()
107         }
108     }
109
110     let waker = Arc::new(Waker).into();
111     let mut cx = Context::from_waker(&waker);
112     let mut fut = Box::pin(fut);
113
114     loop {
115         match fut.as_mut().poll(&mut cx) {
116             Poll::Ready(_) => break,
117             Poll::Pending => thread::park(),
118         }
119     }
120 }
121
122 // just tests by whether or not this compiles
123 fn _pending_impl_all_auto_traits<T>() {
124     use std::panic::{RefUnwindSafe, UnwindSafe};
125     fn all_auto_traits<T: Send + Sync + Unpin + UnwindSafe + RefUnwindSafe>() {}
126
127     all_auto_traits::<std::future::Pending<T>>();
128 }