assertables/assert_pending/
assert_pending.rs

1//! Assert an expression is Pending.
2//!
3//! Pseudocode:<br>
4//! a is Pending
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//! use std::task::Poll;
11//! use std::task::Poll::*;
12//!
13//! let a: Poll<i8> = Pending;
14//! assert_pending!(a);
15//! ```
16//!
17//! # Module macros
18//!
19//! * [`assert_pending`](macro@crate::assert_pending)
20//! * [`assert_pending_as_result`](macro@crate::assert_pending_as_result)
21//! * [`debug_assert_pending`](macro@crate::debug_assert_pending)
22
23/// Assert an expression.is_pending() is true.
24///
25/// Pseudocode:<br>
26/// a is Pending
27///
28/// * If true, return Result `Ok(())`.
29///
30/// * Otherwise, return Result `Err(message)`.
31///
32/// This macro is useful for runtime checks, such as checking parameters,
33/// or sanitizing inputs, or handling different results in different ways.
34///
35/// # Module macros
36///
37/// * [`assert_pending`](macro@crate::assert_pending)
38/// * [`assert_pending_as_result`](macro@crate::assert_pending_as_result)
39/// * [`debug_assert_pending`](macro@crate::debug_assert_pending)
40///
41#[macro_export]
42macro_rules! assert_pending_as_result {
43    ($a:expr $(,)?) => {
44        match (&$a) {
45            a => match (a) {
46                Pending => Ok(()),
47                _ => Err(format!(
48                    concat!(
49                        "assertion failed: `assert_pending!(a)`\n",
50                        "https://docs.rs/assertables/9.8.2/assertables/macro.assert_pending.html\n",
51                        " a label: `{}`,\n",
52                        " a debug: `{:?}`",
53                    ),
54                    stringify!($a),
55                    a
56                )),
57            },
58        }
59    };
60}
61
62#[cfg(test)]
63mod test_assert_pending_as_result {
64    use std::sync::Once;
65    use std::task::Poll;
66    use std::task::Poll::*;
67
68    #[test]
69    fn success() {
70        let a: Poll<i8> = Pending;
71        for _ in 0..1 {
72            let actual = assert_pending_as_result!(a);
73            assert_eq!(actual.unwrap(), ());
74        }
75    }
76
77    #[test]
78    fn success_once() {
79        static A: Once = Once::new();
80        fn a() -> Poll<i8> {
81            if A.is_completed() {
82                panic!("A.is_completed()")
83            } else {
84                A.call_once(|| {})
85            }
86            Pending
87        }
88
89        assert_eq!(A.is_completed(), false);
90        let result = assert_pending_as_result!(a());
91        assert!(result.is_ok());
92        assert_eq!(A.is_completed(), true);
93    }
94
95    #[test]
96    fn failure() {
97        let a: Poll<i8> = Ready(1);
98        let actual = assert_pending_as_result!(a);
99        let message = concat!(
100            "assertion failed: `assert_pending!(a)`\n",
101            "https://docs.rs/assertables/9.8.2/assertables/macro.assert_pending.html\n",
102            " a label: `a`,\n",
103            " a debug: `Ready(1)`"
104        );
105        assert_eq!(actual.unwrap_err(), message);
106    }
107}
108
109/// Assert an expression is Pending.
110///
111/// Pseudocode:<br>
112/// a is Pending
113///
114/// * If true, return `()`.
115///
116/// * Otherwise, call [`panic!`] with a message and the values of the
117///   expressions with their debug representations.
118///
119/// # Examples
120///
121/// ```rust
122/// use assertables::*;
123/// # use std::panic;
124/// use std::task::Poll;
125/// use std::task::Poll::*;
126/// # fn main() {
127/// let a: Poll<i8> = Pending;
128/// assert_pending!(a);
129///
130/// # let result = panic::catch_unwind(|| {
131/// // This will panic
132/// let a: Poll<i8> = Ready(1);
133/// assert_pending!(a);
134/// # });
135/// // assertion failed: `assert_pending!(a)`
136/// // https://docs.rs/assertables/…/assertables/macro.assert_pending.html
137/// //  a label: `a`,
138/// //  a debug: `Ready(1)`
139/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
140/// # let message = concat!(
141/// #     "assertion failed: `assert_pending!(a)`\n",
142/// #     "https://docs.rs/assertables/9.8.2/assertables/macro.assert_pending.html\n",
143/// #     " a label: `a`,\n",
144/// #     " a debug: `Ready(1)`",
145/// # );
146/// # assert_eq!(actual, message);
147/// # }
148/// ```
149///
150/// # Module macros
151///
152/// * [`assert_pending`](macro@crate::assert_pending)
153/// * [`assert_pending_as_result`](macro@crate::assert_pending_as_result)
154/// * [`debug_assert_pending`](macro@crate::debug_assert_pending)
155///
156#[macro_export]
157macro_rules! assert_pending {
158    ($a:expr $(,)?) => {
159        match $crate::assert_pending_as_result!($a) {
160            Ok(()) => (),
161            Err(err) => panic!("{}", err),
162        }
163    };
164    ($a:expr, $($message:tt)+) => {
165        match $crate::assert_pending_as_result!($a) {
166            Ok(()) => (),
167            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
168        }
169    };
170}
171
172#[cfg(test)]
173mod test_assert_pending {
174    use std::panic;
175    use std::task::Poll;
176    use std::task::Poll::*;
177
178    #[test]
179    fn success() {
180        let a: Poll<i8> = Pending;
181        for _ in 0..1 {
182            let actual = assert_pending!(a);
183            assert_eq!(actual, ());
184        }
185    }
186
187    #[test]
188    fn failure() {
189        let a: Poll<i8> = Ready(1);
190        let result = panic::catch_unwind(|| {
191            let _actual = assert_pending!(a);
192        });
193        let message = concat!(
194            "assertion failed: `assert_pending!(a)`\n",
195            "https://docs.rs/assertables/9.8.2/assertables/macro.assert_pending.html\n",
196            " a label: `a`,\n",
197            " a debug: `Ready(1)`"
198        );
199        assert_eq!(
200            result
201                .unwrap_err()
202                .downcast::<String>()
203                .unwrap()
204                .to_string(),
205            message
206        );
207    }
208}
209
210/// Assert an expression is Pending.
211///
212/// Pseudocode:<br>
213/// a is Pending
214///
215/// This macro provides the same statements as [`assert_pending`](macro.assert_pending.html),
216/// except this macro's statements are only enabled in non-optimized
217/// builds by default. An optimized build will not execute this macro's
218/// statements unless `-C debug-assertions` is passed to the compiler.
219///
220/// This macro is useful for checks that are too expensive to be present
221/// in a release build but may be helpful during development.
222///
223/// The result of expanding this macro is always type checked.
224///
225/// An unchecked assertion allows a program in an inconsistent state to
226/// keep running, which might have unexpected consequences but does not
227/// introduce unsafety as long as this only happens in safe code. The
228/// performance cost of assertions, however, is not measurable in general.
229/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
230/// after thorough profiling, and more importantly, only in safe code!
231///
232/// This macro is intended to work in a similar way to
233/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
234///
235/// # Module macros
236///
237/// * [`assert_pending`](macro@crate::assert_pending)
238/// * [`assert_pending`](macro@crate::assert_pending)
239/// * [`debug_assert_pending`](macro@crate::debug_assert_pending)
240///
241#[macro_export]
242macro_rules! debug_assert_pending {
243    ($($arg:tt)*) => {
244        if $crate::cfg!(debug_assertions) {
245            $crate::assert_pending!($($arg)*);
246        }
247    };
248}