claims/
assert_ok.rs

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