assertables/assert_err/
assert_err_ne_x.rs

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