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}