claims/
assert_ready_ok.rs

1/// Asserts that the expression matches a [`Poll::Ready(Ok(_))`] variant, returning the contained
2/// value.
3///
4/// ## Uses
5///
6/// Assertions are always checked in both debug and release builds, and cannot be disabled.
7/// See [`debug_assert_ready_ok!`] for assertions that are not enabled in release builds by default.
8///
9/// ## Custom messages
10///
11/// This macro has a second form, where a custom panic message can be provided with or without
12/// arguments for formatting. See [`std::fmt`] for syntax for this form.
13///
14/// ## Examples
15///
16/// ```rust
17/// # #[macro_use] extern crate claims;
18/// # use std::task::Poll;
19/// # fn main() {
20/// let res: Poll<Result<i32, ()>> = Poll::Ready(Ok(42));
21///
22/// assert_ready_ok!(res);
23/// # }
24/// ```
25///
26/// The contained value will also be returned from this macro call:
27///
28/// ```rust
29/// # #[macro_use] extern crate claims;
30/// # use std::task::Poll;
31/// # fn main() {
32/// let res: Poll<Result<i32, ()>> = Poll::Ready(Ok(42));
33///
34/// let value = assert_ready_ok!(res);
35/// assert_eq!(value, 42);
36/// # }
37/// ```
38///
39/// Both `Poll::Ready(Err(..))` and [`Poll::Pending`] variants will panic:
40///
41/// ```rust,should_panic
42/// # #[macro_use] extern crate claims;
43/// # use std::task::Poll;
44/// # fn main() {
45/// let res: Poll<Result<i32, ()>> = Poll::Ready(Err(()));
46///
47/// assert_ready_ok!(res);  // Will panic
48/// # }
49/// ```
50///
51/// ```rust,should_panic
52/// # #[macro_use] extern crate claims;
53/// # use std::task::Poll;
54/// # fn main() {
55/// let res: Poll<Result<i32, ()>> = Poll::Pending;
56///
57/// assert_ready_ok!(res);  // Will panic
58/// # }
59/// ```
60///
61/// [`Poll::Ready(Ok(T))`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Ready
62/// [`Poll::Pending`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Pending
63/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
64/// [`debug_assert_ready_ok!`]: crate::debug_assert_ready_ok
65#[macro_export]
66macro_rules! assert_ready_ok {
67    ($cond:expr $(,)?) => {
68        match $cond {
69            ::core::task::Poll::Ready(::core::result::Result::Ok(t)) => t,
70            ::core::task::Poll::Ready(::core::result::Result::Err(e)) => ::core::panic!("assertion failed, expected Ready(Ok(_)), got Ready(Err({:?}))", e),
71            ::core::task::Poll::Pending => ::core::panic!("assertion failed, expected Ready(Ok(_)), got Pending"),
72        }
73    };
74    ($cond:expr, $($arg:tt)+) => {
75        match $cond {
76            ::core::task::Poll::Ready(::core::result::Result::Ok(t)) => t,
77            ::core::task::Poll::Ready(::core::result::Result::Err(e)) => ::core::panic!("assertion failed, expected Ready(Ok(_)), got Ready(Err({:?})): {}", e, ::core::format_args!($($arg)+)),
78            ::core::task::Poll::Pending => ::core::panic!("assertion failed, expected Ready(Ok(_)), got Pending: {}", ::core::format_args!($($arg)+)),
79        }
80    };
81}
82
83/// Asserts that the expression matches a [`Poll::Ready(Ok(_))`] variant on debug builds.
84///
85/// This macro behaves nearly the same as [`assert_ready_ok!`] on debug builds, although it does not
86/// return the value contained in the `Poll::Ready(Ok(_))` variant. On release builds it is a no-op.
87///
88/// [`Poll::Ready(Ok(_))`]: https://doc.rust-lang.org/core/task/enum.Poll.html#variant.Ready
89#[macro_export]
90macro_rules! debug_assert_ready_ok {
91    ($($arg:tt)*) => {
92        #[cfg(debug_assertions)]
93        $crate::assert_ready_ok!($($arg)*);
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use core::task::Poll::{Pending, Ready};
100
101    #[test]
102    fn ready_ok() {
103        assert_ready_ok!(Ready(Ok::<_, ()>(())));
104    }
105
106    #[test]
107    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Ready(Err(()))")]
108    fn ready_err() {
109        assert_ready_ok!(Ready(Err::<(), _>(())));
110    }
111
112    #[test]
113    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Pending")]
114    fn not_ready() {
115        assert_ready_ok!(Pending::<Result<(), ()>>);
116    }
117
118    #[test]
119    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Ready(Err(())): foo")]
120    fn ready_err_custom_message() {
121        assert_ready_ok!(Ready(Err::<(), _>(())), "foo");
122    }
123
124    #[test]
125    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Pending: foo")]
126    fn not_ready_custom_message() {
127        assert_ready_ok!(Pending::<Result<(), ()>>, "foo");
128    }
129
130    #[test]
131    fn ready_ok_value_returned() {
132        let value = assert_ready_ok!(Ready(Ok::<_, ()>(42)));
133        assert_eq!(value, 42);
134    }
135
136    #[test]
137    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
138    fn debug_ready_ok() {
139        debug_assert_ready_ok!(Ready(Ok::<_, ()>(())));
140    }
141
142    #[test]
143    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
144    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Ready(Err(()))")]
145    fn debug_ready_err() {
146        debug_assert_ready_ok!(Ready(Err::<(), _>(())));
147    }
148
149    #[test]
150    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
151    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Pending")]
152    fn debug_not_ready() {
153        debug_assert_ready_ok!(Pending::<Result<(), ()>>);
154    }
155
156    #[test]
157    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
158    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Ready(Err(())): foo")]
159    fn debug_ready_err_custom_message() {
160        debug_assert_ready_ok!(Ready(Err::<(), _>(())), "foo");
161    }
162
163    #[test]
164    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
165    #[should_panic(expected = "assertion failed, expected Ready(Ok(_)), got Pending: foo")]
166    fn debug_not_ready_custom_message() {
167        debug_assert_ready_ok!(Pending::<Result<(), ()>>, "foo");
168    }
169
170    #[test]
171    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
172    fn debug_release_ready_err() {
173        debug_assert_ready_ok!(Ready(Err::<(), _>(())));
174    }
175
176    #[test]
177    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
178    fn debug_release_not_ready() {
179        debug_assert_ready_ok!(Pending::<Result<(), ()>>);
180    }
181
182    #[test]
183    fn does_not_require_ok_to_impl_debug() {
184        enum Foo {
185            Bar,
186        }
187
188        assert_ready_ok!(Ready(Ok::<_, ()>(Foo::Bar)));
189    }
190
191    #[test]
192    fn debug_does_not_require_ok_to_impl_debug() {
193        #[allow(dead_code)]
194        enum Foo {
195            Bar,
196        }
197
198        debug_assert_ready_ok!(Ready(Ok::<_, ()>(Foo::Bar)));
199    }
200
201    #[test]
202    fn does_not_require_ok_to_impl_debug_custom_message() {
203        enum Foo {
204            Bar,
205        }
206
207        assert_ready_ok!(Ready(Ok::<_, ()>(Foo::Bar)), "foo");
208    }
209
210    #[test]
211    fn debug_does_not_require_ok_to_impl_debug_custom_message() {
212        #[allow(dead_code)]
213        enum Foo {
214            Bar,
215        }
216
217        debug_assert_ready_ok!(Ready(Ok::<_, ()>(Foo::Bar)), "foo");
218    }
219}