claims/
assert_ready.rs

1/// Asserts that the expression matches a [`Poll::Ready(_)`] variant.
2///
3/// ## Uses
4///
5/// Assertions are always checked in both debug and release builds, and cannot be disabled.
6/// See [`debug_assert_ready!`] 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::Ready(42);
20///
21/// assert_ready!(res);
22/// # }
23/// ```
24///
25/// The contained value will also be returned from this macro call:
26///
27/// ```rust
28/// # #[macro_use] extern crate claims;
29/// # use std::task::Poll;
30/// # fn main() {
31/// let res = Poll::Ready(42);
32///
33/// let value = assert_ready!(res);
34/// assert_eq!(value, 42);
35/// # }
36/// ```
37///
38/// A [`Poll::Pending`] variant will panic:
39///
40/// ```rust,should_panic
41/// # #[macro_use] extern crate claims;
42/// # use std::task::Poll;
43/// # fn main() {
44/// let res = Poll::Pending;
45///
46/// assert_ready!(res);  // Will panic
47/// # }
48/// ```
49///
50/// [`Poll::Ready(_)`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Ready
51/// [`Poll::Pending`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Pending
52/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
53/// [`debug_assert_ready!`]: crate::debug_assert_ready!
54#[macro_export]
55macro_rules! assert_ready {
56    ($cond:expr $(,)?) => {
57        match $cond {
58            ::core::task::Poll::Ready(t) => t,
59            ::core::task::Poll::Pending => {
60                ::core::panic!("assertion failed, expected Ready(_), got Pending");
61            }
62        }
63    };
64    ($cond:expr, $($arg:tt)+) => {
65        match $cond {
66            ::core::task::Poll::Ready(t) => t,
67            ::core::task::Poll::Pending => {
68                ::core::panic!("assertion failed, expected Ready(_), got Pending: {}", ::core::format_args!($($arg)+));
69            }
70        }
71    };
72}
73
74/// Asserts that the expression matches a [`Poll::Ready(_)`] variant on debug builds.
75///
76/// This macro behaves nearly the same as [`assert_ready!`] on debug builds, although it does not
77/// return the value contained in the `Ready` variant. On release builds it is a no-op.
78///
79/// [`Poll::Ready(_)`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Ready
80#[macro_export]
81macro_rules! debug_assert_ready {
82    ($($arg:tt)*) => {
83        #[cfg(debug_assertions)]
84        $crate::assert_ready!($($arg)*);
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use core::task::Poll::{Pending, Ready};
91
92    #[test]
93    fn ready() {
94        assert_ready!(Ready(()));
95    }
96
97    #[test]
98    #[should_panic(expected = "assertion failed, expected Ready(_), got Pending")]
99    fn not_ready() {
100        assert_ready!(Pending::<()>);
101    }
102
103    #[test]
104    #[should_panic(expected = "assertion failed, expected Ready(_), got Pending: foo")]
105    fn not_ready_custom_message() {
106        assert_ready!(Pending::<()>, "foo");
107    }
108
109    #[test]
110    fn ready_value_returned() {
111        let value = assert_ready!(Ready(42));
112        assert_eq!(value, 42);
113    }
114
115    #[test]
116    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
117    fn debug_ready() {
118        debug_assert_ready!(Ready(()));
119    }
120
121    #[test]
122    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
123    #[should_panic(expected = "assertion failed, expected Ready(_), got Pending")]
124    fn debug_not_ready() {
125        debug_assert_ready!(Pending::<()>);
126    }
127
128    #[test]
129    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
130    #[should_panic(expected = "assertion failed, expected Ready(_), got Pending: foo")]
131    fn debug_not_ready_custom_message() {
132        debug_assert_ready!(Pending::<()>, "foo");
133    }
134
135    #[test]
136    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
137    fn debug_release_not_ready() {
138        debug_assert_ready!(Pending::<()>);
139    }
140
141    #[test]
142    fn does_not_require_ready_to_impl_debug() {
143        enum Foo {
144            Bar,
145        }
146
147        assert_ready!(Ready(Foo::Bar));
148    }
149
150    #[test]
151    fn debug_does_not_require_ready_to_impl_debug() {
152        #[allow(dead_code)]
153        enum Foo {
154            Bar,
155        }
156
157        debug_assert_ready!(Ready(Foo::Bar));
158    }
159
160    #[test]
161    fn does_not_require_ready_to_impl_debug_custom_message() {
162        enum Foo {
163            Bar,
164        }
165
166        assert_ready!(Ready(Foo::Bar), "foo");
167    }
168
169    #[test]
170    fn debug_does_not_require_ready_to_impl_debug_custom_message() {
171        #[allow(dead_code)]
172        enum Foo {
173            Bar,
174        }
175
176        debug_assert_ready!(Ready(Foo::Bar), "foo");
177    }
178}