1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
//! Helpers which assist in testing applications based on lifeline. /// Blocks on the future, using a new async runtime. /// This is helpful in doctests #[cfg(feature = "tokio-executor")] pub fn block_on<Fut: std::future::Future<Output = Out>, Out>(fut: Fut) -> Out { use tokio::runtime::Builder; let runtime = Builder::new_current_thread() .build() .expect("doctest runtime creation failed"); runtime.block_on(fut) } // forked from https://github.com/tokio-rs/tokio/pull/2522/files // thank you https://github.com/RadicalZephyr !! // this was just what Lifeline needs. /// Asserts that the expression completes within a given number of milliseconds. /// /// This will invoke the `panic!` macro if the provided future /// expression fails to complete within the given number of /// milliseconds. This macro expands to an `await` and must be /// invoked inside an async context. /// /// A default timeout of 50ms is used if no duration is passed. /// /// # Examples /// /// ```rust /// use lifeline::assert_completes; /// use tokio::time::sleep; /// /// # let fut = /// async { /// // Succeeds because default time is longer than delay. /// assert_completes!(sleep(Duration::from_millis(5))); /// } /// # ; /// # let mut runtime = tokio::runtime::Runtime::new().unwrap(); /// # runtime.block_on(fut); ///``` /// /// ```rust,should_panic /// use lifeline::assert_completes; /// use tokio::time::sleep; /// /// # let fut = /// async { /// // Fails because timeout is shorter than delay. /// assert_completes!(sleep(Duration::from_millis(250)), 10); /// } /// # ; /// # let mut runtime = tokio::runtime::Runtime::new().unwrap(); /// # runtime.block_on(fut); /// ``` #[macro_export] macro_rules! assert_completes { ($e:expr) => { $crate::assert_completes!($e, 50) }; ($e:expr, $time:literal) => {{ use std::time::Duration; use tokio::time::timeout; match timeout(Duration::from_millis($time), $e).await { Ok(ret) => ret, Err(_) => panic!( "assertion failed: {} timed out after {} ms", stringify!($e), $time, ), } }}; } /// Asserts that the expression does not complete within a given number of milliseconds. /// /// This will invoke the `panic!` macro if the provided future /// expression completes within the given number of milliseconds. /// This macro expands to an `await` and must be invoked inside an /// async context. /// ///A default timeout of 50ms is used if no duration is passed. /// /// # Examples /// /// ```rust,should_panic /// use lifeline::assert_times_out; /// use tokio::time::sleep; /// /// # let fut = /// async { /// // Fails because default time is longer than delay. /// assert_times_out!(sleep(Duration::from_millis(5))); /// } /// # ; /// # let mut runtime = tokio::runtime::Runtime::new().unwrap(); /// # runtime.block_on(fut); /// ``` /// /// ```rust /// use lifeline::assert_times_out; /// use tokio::time::sleep; /// /// # let fut = /// async { /// // Succeeds because timeout is shorter than delay. /// assert_times_out!(sleep(Duration::from_millis(250)), 10); /// } /// # ; /// # let mut runtime = tokio::runtime::Runtime::new().unwrap(); /// # runtime.block_on(fut); /// ``` #[macro_export] macro_rules! assert_times_out { ($e:expr) => { $crate::assert_times_out!($e, 50) }; ($e:expr, $time:literal) => {{ use std::time::Duration; use tokio::time::timeout; match timeout(Duration::from_millis($time), $e).await { Ok(_) => panic!( "assertion failed: {} completed within {} ms", stringify!($e), $time, ), Err(err) => err, } }}; }