futures_test/future/mod.rs
1//! Additional combinators for testing futures.
2
3mod pending_once;
4pub use self::pending_once::PendingOnce;
5
6use futures_core::future::Future;
7use std::thread;
8
9pub use crate::assert_unmoved::AssertUnmoved;
10pub use crate::interleave_pending::InterleavePending;
11
12/// Additional combinators for testing futures.
13pub trait FutureTestExt: Future {
14 /// Asserts that the given is not moved after being polled.
15 ///
16 /// A check for movement is performed each time the future is polled
17 /// and when `Drop` is called.
18 ///
19 /// Aside from keeping track of the location at which the future was first
20 /// polled and providing assertions, this future adds no runtime behavior
21 /// and simply delegates to the child future.
22 fn assert_unmoved(self) -> AssertUnmoved<Self>
23 where
24 Self: Sized,
25 {
26 AssertUnmoved::new(self)
27 }
28
29 /// Introduces one [`Poll::Pending`](futures_core::task::Poll::Pending)
30 /// before polling the given future.
31 ///
32 /// # Examples
33 ///
34 /// ```
35 /// use core::pin::pin;
36 ///
37 /// use futures::task::Poll;
38 /// use futures::future::FutureExt;
39 /// use futures_test::task::noop_context;
40 /// use futures_test::future::FutureTestExt;
41 ///
42 /// let future = (async { 5 }).pending_once();
43 /// let mut future = pin!(future);
44 ///
45 /// let mut cx = noop_context();
46 ///
47 /// assert_eq!(future.poll_unpin(&mut cx), Poll::Pending);
48 /// assert_eq!(future.poll_unpin(&mut cx), Poll::Ready(5));
49 /// ```
50 fn pending_once(self) -> PendingOnce<Self>
51 where
52 Self: Sized,
53 {
54 PendingOnce::new(self)
55 }
56
57 /// Runs this future on a dedicated executor running in a background thread.
58 ///
59 /// # Examples
60 ///
61 /// ```
62 /// # futures::executor::block_on(async {
63 /// use futures::channel::oneshot;
64 /// use futures_test::future::FutureTestExt;
65 ///
66 /// let (tx, rx) = oneshot::channel::<i32>();
67 ///
68 /// (async { tx.send(5).unwrap() }).run_in_background();
69 ///
70 /// assert_eq!(rx.await, Ok(5));
71 /// # });
72 /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371
73 /// ```
74 fn run_in_background(self)
75 where
76 Self: Sized + Send + 'static,
77 Self::Output: Send,
78 {
79 thread::spawn(|| futures_executor::block_on(self));
80 }
81
82 /// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending)
83 /// in between each call to poll.
84 ///
85 /// # Examples
86 ///
87 /// ```
88 /// use core::pin::pin;
89 ///
90 /// use futures::task::Poll;
91 /// use futures::future::{self, Future};
92 /// use futures_test::task::noop_context;
93 /// use futures_test::future::FutureTestExt;
94 ///
95 /// let future = future::ready(1).interleave_pending();
96 /// let mut future = pin!(future);
97 ///
98 /// let mut cx = noop_context();
99 ///
100 /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Pending);
101 /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(1));
102 /// ```
103 fn interleave_pending(self) -> InterleavePending<Self>
104 where
105 Self: Sized,
106 {
107 InterleavePending::new(self)
108 }
109}
110
111impl<Fut> FutureTestExt for Fut where Fut: Future {}