claims/assert_pending.rs
1/// Asserts that the expression matches a [`Poll::Pending`] variant.
2///
3/// ## Uses
4///
5/// Assertions are always checked in both debug and release builds, and cannot be disabled.
6/// See [`debug_assert_pending!`] for assertions that are not enabled in release builds by default.
7///
8/// ## Custom messages
9///
10/// This macro has a second form, where a custom panic message can be provided with or without
11/// arguments for formatting. See [`std::fmt`] for syntax for this form.
12///
13/// ## Examples
14///
15/// ```rust
16/// # #[macro_use] extern crate claims;
17/// # use std::task::Poll;
18/// # fn main() {
19/// let res: Poll<i32> = Poll::Pending;
20///
21/// assert_pending!(res);
22///
23/// // With a custom message
24/// assert_pending!(res, "Future is not ready yet");
25/// # }
26/// ```
27///
28/// A [`Poll::Pending`] variant will also be returned from this macro call:
29///
30/// ```rust
31/// # #[macro_use] extern crate claims;
32/// # use std::task::Poll;
33/// # fn main() {
34/// let res: Poll<i32> = Poll::Pending;
35///
36/// let value = assert_pending!(res);
37/// assert_eq!(value, Poll::Pending);
38/// # }
39/// ```
40///
41/// A [`Poll::Ready(_)`] variant will panic:
42///
43/// ```rust,should_panic
44/// # #[macro_use] extern crate claims;
45/// # use std::task::Poll;
46/// # fn main() {
47/// let res = Poll::Ready(42);
48///
49/// assert_pending!(res); // Will panic
50/// # }
51/// ```
52///
53/// [`Poll::Ready(_)`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Ready
54/// [`Poll::Pending`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Pending
55/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
56/// [`debug_assert_pending!`]: crate::debug_assert_pending!
57#[macro_export]
58macro_rules! assert_pending {
59 ($cond:expr $(,)?) => {
60 match $cond {
61 pending @ ::core::task::Poll::Pending => pending,
62 ready @ ::core::task::Poll::Ready(_) => {
63 ::core::panic!("assertion failed, expected Pending, got {:?}", ready);
64 }
65 }
66 };
67 ($cond:expr, $($arg:tt)+) => {
68 match $cond {
69 pending @ ::core::task::Poll::Pending => pending,
70 ready @ ::core::task::Poll::Ready(_) => {
71 ::core::panic!("assertion failed, expected Pending, got {:?}: {}", ready, ::core::format_args!($($arg)+));
72 }
73 }
74 };
75}
76
77/// Asserts that the expression matches a [`Poll::Pending`] variant on debug builds.
78///
79/// This macro behaves the same as [`assert_pending!`] on debug builds. On release builds it is a
80/// no-op.
81///
82/// [`Poll::Pending`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Pending
83#[macro_export]
84macro_rules! debug_assert_pending {
85 ($($arg:tt)*) => {
86 #[allow(unused_must_use)]
87 #[cfg(debug_assertions)]
88 {
89 $crate::assert_pending!($($arg)*);
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use core::task::Poll::{Pending, Ready};
97
98 #[test]
99 fn pending() {
100 let _ = assert_pending!(Pending::<()>);
101 }
102
103 #[test]
104 #[should_panic(expected = "assertion failed, expected Pending, got Ready(())")]
105 fn not_pending() {
106 let _ = assert_pending!(Ready(()));
107 }
108
109 #[test]
110 #[should_panic(expected = "assertion failed, expected Pending, got Ready(()): foo")]
111 fn not_pending_custom_message() {
112 let _ = assert_pending!(Ready(()), "foo");
113 }
114
115 #[test]
116 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
117 fn debug_pending() {
118 debug_assert_pending!(Pending::<()>);
119 }
120
121 #[test]
122 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
123 #[should_panic(expected = "assertion failed, expected Pending, got Ready(())")]
124 fn debug_not_pending() {
125 debug_assert_pending!(Ready(()));
126 }
127
128 #[test]
129 #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
130 #[should_panic(expected = "assertion failed, expected Pending, got Ready(()): foo")]
131 fn debug_not_pending_custom_message() {
132 debug_assert_pending!(Ready(()), "foo");
133 }
134
135 #[test]
136 #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
137 fn debug_release_not_pending() {
138 debug_assert_pending!(Ready(()));
139 }
140}