1 //! Additional combinators for testing futures. 2 3 mod pending_once; 4 pub use self::pending_once::PendingOnce; 5 6 use futures_core::future::Future; 7 use std::thread; 8 9 pub use crate::assert_unmoved::AssertUnmoved; 10 pub use crate::interleave_pending::InterleavePending; 11 12 /// Additional combinators for testing futures. 13 pub 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. assert_unmoved(self) -> AssertUnmoved<Self> where Self: Sized,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 futures::task::Poll; 36 /// use futures::future::FutureExt; 37 /// use futures_test::task::noop_context; 38 /// use futures_test::future::FutureTestExt; 39 /// use futures::pin_mut; 40 /// 41 /// let future = (async { 5 }).pending_once(); 42 /// pin_mut!(future); 43 /// 44 /// let mut cx = noop_context(); 45 /// 46 /// assert_eq!(future.poll_unpin(&mut cx), Poll::Pending); 47 /// assert_eq!(future.poll_unpin(&mut cx), Poll::Ready(5)); 48 /// ``` pending_once(self) -> PendingOnce<Self> where Self: Sized,49 fn pending_once(self) -> PendingOnce<Self> 50 where 51 Self: Sized, 52 { 53 PendingOnce::new(self) 54 } 55 56 /// Runs this future on a dedicated executor running in a background thread. 57 /// 58 /// # Examples 59 /// 60 /// ``` 61 /// # futures::executor::block_on(async { 62 /// use futures::channel::oneshot; 63 /// use futures_test::future::FutureTestExt; 64 /// 65 /// let (tx, rx) = oneshot::channel::<i32>(); 66 /// 67 /// (async { tx.send(5).unwrap() }).run_in_background(); 68 /// 69 /// assert_eq!(rx.await, Ok(5)); 70 /// # }); 71 /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371 72 /// ``` run_in_background(self) where Self: Sized + Send + 'static, Self::Output: Send,73 fn run_in_background(self) 74 where 75 Self: Sized + Send + 'static, 76 Self::Output: Send, 77 { 78 thread::spawn(|| futures_executor::block_on(self)); 79 } 80 81 /// Introduces an extra [`Poll::Pending`](futures_core::task::Poll::Pending) 82 /// in between each call to poll. 83 /// 84 /// # Examples 85 /// 86 /// ``` 87 /// use futures::task::Poll; 88 /// use futures::future::{self, Future}; 89 /// use futures_test::task::noop_context; 90 /// use futures_test::future::FutureTestExt; 91 /// use futures::pin_mut; 92 /// 93 /// let future = future::ready(1).interleave_pending(); 94 /// pin_mut!(future); 95 /// 96 /// let mut cx = noop_context(); 97 /// 98 /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Pending); 99 /// assert_eq!(future.as_mut().poll(&mut cx), Poll::Ready(1)); 100 /// ``` interleave_pending(self) -> InterleavePending<Self> where Self: Sized,101 fn interleave_pending(self) -> InterleavePending<Self> 102 where 103 Self: Sized, 104 { 105 InterleavePending::new(self) 106 } 107 } 108 109 impl<Fut> FutureTestExt for Fut where Fut: Future {} 110