claims/
assert_some_eq.rs

1/// Asserts that the left expression contains a [`Some(T)`] variant and its contained value of type
2/// `T` equals the right expression.
3///
4/// ## Uses
5///
6/// Assertions are always checked in both debug and release builds, and cannot be disabled.
7/// See [`debug_assert_some_eq!`] 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/// # fn main() {
19/// let maybe = Some(42);
20///
21/// assert_some_eq!(maybe, 42);
22///
23/// // With a custom message
24/// assert_some_eq!(maybe, 42, "Got some value");
25/// # }
26/// ```
27///
28/// A `None` variant will panic:
29///
30/// ```rust,should_panic
31/// # #[macro_use] extern crate claims;
32/// # fn main() {
33/// let maybe: Option<i32> = None;
34///
35/// assert_some_eq!(maybe, 42);  // Will panic
36/// # }
37/// ```
38///
39/// [`Some(T)`]: https://doc.rust-lang.org/core/option/enum.Option.html#variant.Some
40/// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html
41/// [`debug_assert_some_eq!`]: crate::debug_assert_some_eq!
42#[macro_export]
43macro_rules! assert_some_eq {
44    ($cond:expr, $expected:expr $(,)?) => {
45        match $cond {
46            ::core::option::Option::Some(t) => {
47                ::core::assert_eq!(t, $expected);
48                t
49            },
50            ::core::option::Option::None => {
51                ::core::panic!("assertion failed, expected Some(_), got None");
52            }
53        }
54    };
55    ($cond:expr, $expected:expr, $($arg:tt)+) => {
56        match $cond {
57            ::core::option::Option::Some(t) => {
58                ::core::assert_eq!(t, $expected, $($arg)+);
59                t
60            },
61            ::core::option::Option::None => {
62                ::core::panic!("assertion failed, expected Some(_), got None: {}", ::core::format_args!($($arg)+));
63            }
64        }
65    };
66}
67
68/// Asserts that the left expression contains a [`Some(T)`] variant and its contained value of type
69/// `T` equals the right expression on debug builds.
70///
71/// This macro behaves nearly the same as [`assert_some_eq!`] on debug builds, although it does not
72/// return the value contained in the `Some` variant. On release builds it is a no-op.
73///
74/// [`Some(T)`]: https://doc.rust-lang.org/core/option/enum.Option.html#variant.Some
75#[macro_export]
76macro_rules! debug_assert_some_eq {
77    ($($arg:tt)*) => {
78        #[cfg(debug_assertions)]
79        $crate::assert_some_eq!($($arg)*);
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    #[test]
86    fn equal() {
87        assert_some_eq!(Some(42), 42);
88    }
89
90    #[test]
91    #[should_panic]
92    fn not_equal() {
93        assert_some_eq!(Some(42), 100);
94    }
95
96    #[test]
97    #[should_panic(expected = "assertion failed, expected Some(_), got None")]
98    fn not_some() {
99        assert_some_eq!(None::<usize>, 42);
100    }
101
102    #[test]
103    #[should_panic(expected = "foo")]
104    fn not_equal_custom_message() {
105        assert_some_eq!(Some(1), 2, "foo");
106    }
107
108    #[test]
109    #[should_panic(expected = "assertion failed, expected Some(_), got None: foo")]
110    fn not_some_custom_message() {
111        assert_some_eq!(None::<usize>, 2, "foo");
112    }
113
114    #[test]
115    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
116    fn debug_equal() {
117        debug_assert_some_eq!(Some(42), 42);
118    }
119
120    #[test]
121    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
122    #[should_panic]
123    fn debug_not_equal() {
124        debug_assert_some_eq!(Some(42), 100);
125    }
126
127    #[test]
128    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
129    #[should_panic(expected = "assertion failed, expected Some(_), got None")]
130    fn debug_not_some() {
131        debug_assert_some_eq!(None::<usize>, 42);
132    }
133
134    #[test]
135    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
136    #[should_panic(expected = "foo")]
137    fn debug_not_equal_custom_message() {
138        debug_assert_some_eq!(Some(1), 2, "foo");
139    }
140
141    #[test]
142    #[cfg_attr(not(debug_assertions), ignore = "only run in debug mode")]
143    #[should_panic(expected = "assertion failed, expected Some(_), got None: foo")]
144    fn debug_not_some_custom_message() {
145        debug_assert_some_eq!(None::<usize>, 2, "foo");
146    }
147
148    #[test]
149    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
150    fn debug_release_not_equal() {
151        debug_assert_some_eq!(Some(42), 100);
152    }
153
154    #[test]
155    #[cfg_attr(debug_assertions, ignore = "only run in release mode")]
156    fn debug_release_not_some() {
157        debug_assert_some_eq!(None::<usize>, 42);
158    }
159}