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