assertables/assert_ok/assert_ok_eq_x.rs
1//! Assert an expression is Ok and its value is equal to an expression.
2//!
3//! Pseudocode:<br>
4//! (a ⇒ Ok(a1) ⇒ a1) = b
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! let a: Result<i8, i8> = Ok(1);
12//! let b: i8 = 1;
13//! assert_ok_eq_x!(a, b);
14//! ```
15//!
16//! # Module macros
17//!
18//! * [`assert_ok_eq_x`](macro@crate::assert_ok_eq_x)
19//! * [`assert_ok_eq_x_as_result`](macro@crate::assert_ok_eq_x_as_result)
20//! * [`debug_assert_ok_eq_x`](macro@crate::debug_assert_ok_eq_x)
21
22/// Assert an expression is Ok and its value is equal to an expression.
23///
24/// Pseudocode:<br>
25/// (a ⇒ Ok(a1) ⇒ a1) = b
26///
27/// * If true, return Result `Ok(a1)`.
28///
29/// * Otherwise, return Result `Err(message)`.
30///
31/// This macro is useful for runtime checks, such as checking parameters,
32/// or sanitizing inputs, or handling different results in different ways.
33///
34/// # Module macros
35///
36/// * [`assert_ok_eq_x`](macro@crate::assert_ok_eq_x)
37/// * [`assert_ok_eq_x_as_result`](macro@crate::assert_ok_eq_x_as_result)
38/// * [`debug_assert_ok_eq_x`](macro@crate::debug_assert_ok_eq_x)
39///
40#[macro_export]
41macro_rules! assert_ok_eq_x_as_result {
42 ($a:expr, $b:expr $(,)?) => {
43 match($a, $b) {
44 (a, b) => {
45 match (a) {
46 Ok(a1) => {
47 if a1 == b {
48 Ok(a1)
49 } else {
50 Err(
51 format!(
52 concat!(
53 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
54 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
55 " a label: `{}`,\n",
56 " a debug: `{:?}`,\n",
57 " a inner: `{:?}`,\n",
58 " b label: `{}`,\n",
59 " b debug: `{:?}`",
60 ),
61 stringify!($a),
62 a,
63 a1,
64 stringify!($b),
65 b
66 )
67 )
68 }
69 },
70 _ => {
71 Err(
72 format!(
73 concat!(
74 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
75 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
76 " a label: `{}`,\n",
77 " a debug: `{:?}`,\n",
78 " b label: `{}`,\n",
79 " b debug: `{:?}`",
80 ),
81 stringify!($a),
82 a,
83 stringify!($b),
84 b
85 )
86 )
87 }
88 }
89 }
90 }
91 };
92}
93
94#[cfg(test)]
95mod test_assert_ok_eq_x_as_result {
96 use std::sync::Once;
97
98 #[test]
99 fn eq() {
100 let a: Result<i8, i8> = Ok(1);
101 let b: i8 = 1;
102 for _ in 0..1 {
103 let actual = assert_ok_eq_x_as_result!(a, b);
104 assert_eq!(actual.unwrap(), 1);
105 }
106 }
107
108 #[test]
109 fn eq_once() {
110 static A: Once = Once::new();
111 fn a() -> Result<i8, i8> {
112 if A.is_completed() {
113 panic!("A.is_completed()")
114 } else {
115 A.call_once(|| {})
116 }
117 Ok(1)
118 }
119
120 static B: Once = Once::new();
121 fn b() -> i8 {
122 if B.is_completed() {
123 panic!("B.is_completed()")
124 } else {
125 B.call_once(|| {})
126 }
127 1
128 }
129
130 assert_eq!(A.is_completed(), false);
131 assert_eq!(B.is_completed(), false);
132 let result = assert_ok_eq_x_as_result!(a(), b());
133 assert!(result.is_ok());
134 assert_eq!(A.is_completed(), true);
135 assert_eq!(B.is_completed(), true);
136 }
137
138 #[test]
139 fn ne() {
140 let a: Result<i8, i8> = Ok(1);
141 let b: i8 = 2;
142 let actual = assert_ok_eq_x_as_result!(a, b);
143 let message = concat!(
144 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
145 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
146 " a label: `a`,\n",
147 " a debug: `Ok(1)`,\n",
148 " a inner: `1`,\n",
149 " b label: `b`,\n",
150 " b debug: `2`"
151 );
152 assert_eq!(actual.unwrap_err(), message);
153 }
154
155 #[test]
156 fn not_ok() {
157 let a: Result<i8, i8> = Err(1);
158 let b: i8 = 1;
159 let actual = assert_ok_eq_x_as_result!(a, b);
160 let message = concat!(
161 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
162 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
163 " a label: `a`,\n",
164 " a debug: `Err(1)`,\n",
165 " b label: `b`,\n",
166 " b debug: `1`",
167 );
168 assert_eq!(actual.unwrap_err(), message);
169 }
170}
171
172/// Assert an expression is Ok and its value is equal to an expression.
173///
174/// Pseudocode:<br>
175/// (a ⇒ Ok(a1) ⇒ a1) = b
176///
177/// * If true, return `a1`.
178///
179/// * Otherwise, call [`panic!`] with a message and the values of the
180/// expressions with their debug representations.
181///
182/// # Examples
183///
184/// ```rust
185/// use assertables::*;
186/// # use std::panic;
187///
188/// # fn main() {
189/// let a: Result<i8, i8> = Ok(1);
190/// let b: i8 = 1;
191/// assert_ok_eq_x!(a, b);
192///
193/// # let result = panic::catch_unwind(|| {
194/// // This will panic
195/// let a: Result<i8, i8> = Ok(1);
196/// let b: i8 = 2;
197/// assert_ok_eq_x!(a, b);
198/// # });
199/// // assertion failed: `assert_ok_eq_x!(a, b)`
200/// // https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html
201/// // a label: `a`,
202/// // a debug: `Ok(1)`,
203/// // a inner: `1`,
204/// // b label: `b`,
205/// // b debug: `2`
206/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
207/// # let message = concat!(
208/// # "assertion failed: `assert_ok_eq_x!(a, b)`\n",
209/// # "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
210/// # " a label: `a`,\n",
211/// # " a debug: `Ok(1)`,\n",
212/// # " a inner: `1`,\n",
213/// # " b label: `b`,\n",
214/// # " b debug: `2`",
215/// # );
216/// # assert_eq!(actual, message);
217/// # }
218/// ```
219///
220/// # Module macros
221///
222/// * [`assert_ok_eq_x`](macro@crate::assert_ok_eq_x)
223/// * [`assert_ok_eq_x_as_result`](macro@crate::assert_ok_eq_x_as_result)
224/// * [`debug_assert_ok_eq_x`](macro@crate::debug_assert_ok_eq_x)
225///
226#[macro_export]
227macro_rules! assert_ok_eq_x {
228 ($a:expr, $b:expr $(,)?) => {
229 match $crate::assert_ok_eq_x_as_result!($a, $b) {
230 Ok(x) => x,
231 Err(err) => panic!("{}", err),
232 }
233 };
234 ($a:expr, $b:expr, $($message:tt)+) => {
235 match $crate::assert_ok_eq_x_as_result!($a, $b) {
236 Ok(x) => x,
237 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
238 }
239 };
240}
241
242#[cfg(test)]
243mod test_assert_ok_eq_x {
244 use std::panic;
245
246 #[test]
247 fn eq() {
248 let a: Result<i8, i8> = Ok(1);
249 let b: i8 = 1;
250 for _ in 0..1 {
251 let actual = assert_ok_eq_x!(a, b);
252 assert_eq!(actual, 1);
253 }
254 }
255
256 #[test]
257 fn ne() {
258 let a: Result<i8, i8> = Ok(1);
259 let b: i8 = 2;
260 let result = panic::catch_unwind(|| {
261 let _actual = assert_ok_eq_x!(a, b);
262 });
263 let message = concat!(
264 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
265 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
266 " a label: `a`,\n",
267 " a debug: `Ok(1)`,\n",
268 " a inner: `1`,\n",
269 " b label: `b`,\n",
270 " b debug: `2`"
271 );
272 assert_eq!(
273 result
274 .unwrap_err()
275 .downcast::<String>()
276 .unwrap()
277 .to_string(),
278 message
279 );
280 }
281
282 #[test]
283 fn not_ok() {
284 let a: Result<i8, i8> = Err(1);
285 let b: i8 = 1;
286 let result = panic::catch_unwind(|| {
287 let _actual = assert_ok_eq_x!(a, b);
288 });
289 let message = concat!(
290 "assertion failed: `assert_ok_eq_x!(a, b)`\n",
291 "https://docs.rs/assertables/9.6.1/assertables/macro.assert_ok_eq_x.html\n",
292 " a label: `a`,\n",
293 " a debug: `Err(1)`,\n",
294 " b label: `b`,\n",
295 " b debug: `1`",
296 );
297 assert_eq!(
298 result
299 .unwrap_err()
300 .downcast::<String>()
301 .unwrap()
302 .to_string(),
303 message
304 );
305 }
306}
307
308/// Assert an expression is Ok and its value is equal to an expression.
309///
310/// Pseudocode:<br>
311/// (a ⇒ Ok(a1) ⇒ a1) = b
312///
313/// This macro provides the same statements as [`assert_ok_eq_x`](macro.assert_ok_eq_x.html),
314/// except this macro's statements are only enabled in non-optimized
315/// builds by default. An optimized build will not execute this macro's
316/// statements unless `-C debug-assertions` is passed to the compiler.
317///
318/// This macro is useful for checks that are too expensive to be present
319/// in a release build but may be helpful during development.
320///
321/// The result of expanding this macro is always type checked.
322///
323/// An unchecked assertion allows a program in an inconsistent state to
324/// keep running, which might have unexpected consequences but does not
325/// introduce unsafety as long as this only happens in safe code. The
326/// performance cost of assertions, however, is not measurable in general.
327/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
328/// after thorough profiling, and more importantly, only in safe code!
329///
330/// This macro is intended to work in a similar way to
331/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
332///
333/// # Module macros
334///
335/// * [`assert_ok_eq_x`](macro@crate::assert_ok_eq_x)
336/// * [`assert_ok_eq_x`](macro@crate::assert_ok_eq_x)
337/// * [`debug_assert_ok_eq_x`](macro@crate::debug_assert_ok_eq_x)
338///
339#[macro_export]
340macro_rules! debug_assert_ok_eq_x {
341 ($($arg:tt)*) => {
342 if $crate::cfg!(debug_assertions) {
343 $crate::assert_ok_eq_x!($($arg)*);
344 }
345 };
346}