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}