assertables/assert_fn_ok/assert_fn_ok_ne_x.rs
1//! Assert a function Ok(…) is not equal to an expression.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Ok(a) ⇒ a) ≠ expr
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//! fn f(i: i8) -> Result<String, String> {
11//! match i {
12//! 0..=9 => Ok(format!("{}", i)),
13//! _ => Err(format!("{:?} is out of range", i)),
14//! }
15//! }
16//!
17//! let a: i8 = 1;
18//! let b = String::from("2");
19//! assert_fn_ok_ne_x!(f, a, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_ok_ne_x`](macro@crate::assert_fn_ok_ne_x)
25//! * [`assert_fn_ok_ne_x_as_result`](macro@crate::assert_fn_ok_ne_x_as_result)
26//! * [`debug_assert_fn_ok_ne_x`](macro@crate::debug_assert_fn_ok_ne_x)
27
28/// Assert a function Ok(…) is not equal to an expression.
29///
30/// Pseudocode:<br>
31/// (a_function(a_param) ⇒ Ok(a) ⇒ a) ≠ expr
32///
33/// * If true, return Result `Ok(a)`.
34///
35/// * Otherwise, return Result `Err(message)`.
36///
37/// This macro is useful for runtime checks, such as checking parameters,
38/// or sanitizing inputs, or handling different results in different ways.
39///
40/// # Module macros
41///
42/// * [`assert_fn_ok_ne_x`](macro@crate::assert_fn_ok_ne_x)
43/// * [`assert_fn_ok_ne_x_as_result`](macro@crate::assert_fn_ok_ne_x_as_result)
44/// * [`debug_assert_fn_ok_ne_x`](macro@crate::debug_assert_fn_ok_ne_x)
45///
46#[macro_export]
47macro_rules! assert_fn_ok_ne_x_as_result {
48
49 //// Arity 1
50
51 ($a_function:path, $a_param:expr, $b_expr:expr $(,)?) => {
52 match (&$a_function, &$a_param, &$b_expr) {
53 (_a_function, a_param, b_expr) => {
54 match ($a_function($a_param)) {
55 Ok(a) => {
56 if a != $b_expr {
57 Ok(a)
58 } else {
59 Err(
60 format!(
61 concat!(
62 "assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`\n",
63 "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_fn_ok_ne_x.html\n",
64 " a_function label: `{}`,\n",
65 " a_param label: `{}`,\n",
66 " a_param debug: `{:?}`,\n",
67 " b_expr label: `{}`,\n",
68 " b_expr debug: `{:?}`,\n",
69 " a: `{:?}`,\n",
70 " b: `{:?}`",
71 ),
72 stringify!($a_function),
73 stringify!($a_param),
74 a_param,
75 stringify!($b_expr),
76 b_expr,
77 a,
78 $b_expr
79 )
80 )
81 }
82 },
83 Err(a) => {
84 Err(
85 format!(
86 concat!(
87 "assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`\n",
88 "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_fn_ok_ne_x.html\n",
89 " a_function label: `{}`,\n",
90 " a_param label: `{}`,\n",
91 " a_param debug: `{:?}`,\n",
92 " b_expr label: `{}`,\n",
93 " b_expr debug: `{:?}`,\n",
94 " a result: `{:?}`",
95 ),
96 stringify!($a_function),
97 stringify!($a_param),
98 a_param,
99 stringify!($b_expr),
100 b_expr,
101 a
102 )
103 )
104 }
105 }
106 }
107 }
108 };
109
110 //// Arity 0
111
112 ($a_function:path, $b_expr:expr $(,)?) => {
113 match (&$a_function, &$b_expr) {
114 (_a_function, b_expr) => {
115 match ($a_function()) {
116 Ok(a) => {
117 if a != $b_expr {
118 Ok(a)
119 } else {
120 Err(
121 format!(
122 concat!(
123 "assertion failed: `assert_fn_ok_ne_x!(a_function, b_expr)`\n",
124 "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_fn_ok_ne_x.html\n",
125 " a_function label: `{}`,\n",
126 " b_expr label: `{}`,\n",
127 " b_expr debug: `{:?}`,\n",
128 " a: `{:?}`,\n",
129 " b: `{:?}`",
130 ),
131 stringify!($a_function),
132 stringify!($b_expr),
133 b_expr,
134 a,
135 $b_expr
136 )
137 )
138 }
139 },
140 a => {
141 Err(
142 format!(
143 concat!(
144 "assertion failed: `assert_fn_ok_ne_x!(a_function, b_expr)`\n",
145 "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_fn_ok_ne_x.html\n",
146 " a_function label: `{}`,\n",
147 " b_expr label: `{}`,\n",
148 " b_expr debug: `{:?}`,\n",
149 " a: `{:?}`",
150 ),
151 stringify!($a_function),
152 stringify!($b_expr),
153 b_expr,
154 a
155 )
156 )
157 }
158 }
159 }
160 }
161 };
162}
163
164#[cfg(test)]
165mod test_assert_fn_ok_ne_x_as_result {
166 // use std::sync::Once;
167
168 mod arity_1 {
169
170 fn f(i: i8) -> Result<i8, i8> {
171 return Ok(i);
172 }
173
174 #[test]
175 fn ne() {
176 let a: i8 = 1;
177 let b: i8 = 2;
178 for _ in 0..1 {
179 let actual = assert_fn_ok_ne_x_as_result!(f, a, b);
180 assert_eq!(actual.unwrap(), 1);
181 }
182 }
183
184 #[test]
185 fn eq() {
186 let a: i8 = 1;
187 let b: i8 = 1;
188 let actual = assert_fn_ok_ne_x_as_result!(f, a, b);
189 let message = concat!(
190 "assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`\n",
191 "https://docs.rs/assertables/",
192 env!("CARGO_PKG_VERSION"),
193 "/assertables/macro.assert_fn_ok_ne_x.html\n",
194 " a_function label: `f`,\n",
195 " a_param label: `a`,\n",
196 " a_param debug: `1`,\n",
197 " b_expr label: `b`,\n",
198 " b_expr debug: `1`,\n",
199 " a: `1`,\n",
200 " b: `1`"
201 );
202 assert_eq!(actual.unwrap_err(), message);
203 }
204 }
205
206 mod arity_0 {
207
208 fn f() -> Result<i8, i8> {
209 return Ok(1);
210 }
211
212 #[test]
213 fn ne() {
214 let b: i8 = 2;
215 for _ in 0..1 {
216 let actual = assert_fn_ok_ne_x_as_result!(f, b);
217 assert_eq!(actual.unwrap(), 1);
218 }
219 }
220
221 #[test]
222 fn eq() {
223 let b: i8 = 1;
224 let actual = assert_fn_ok_ne_x_as_result!(f, b);
225 let message = concat!(
226 "assertion failed: `assert_fn_ok_ne_x!(a_function, b_expr)`\n",
227 "https://docs.rs/assertables/",
228 env!("CARGO_PKG_VERSION"),
229 "/assertables/macro.assert_fn_ok_ne_x.html\n",
230 " a_function label: `f`,\n",
231 " b_expr label: `b`,\n",
232 " b_expr debug: `1`,\n",
233 " a: `1`,\n",
234 " b: `1`"
235 );
236 assert_eq!(actual.unwrap_err(), message);
237 }
238 }
239}
240
241/// Assert a function Ok(…) is not equal to an expression.
242///
243/// Pseudocode:<br>
244/// (a_function(a_param) ⇒ Ok(a) ⇒ a) ≠ expr
245///
246/// * If true, return `a`.
247///
248/// * Otherwise, call [`panic!`] with a message and the values of the
249/// expressions with their debug representations.
250///
251/// # Examples
252///
253/// ```rust
254/// use assertables::*;
255/// # use std::panic;
256/// fn f(i: i8) -> Result<String, String> {
257/// match i {
258/// 0..=9 => Ok(format!("{}", i)),
259/// _ => Err(format!("{:?} is out of range", i)),
260/// }
261/// }
262///
263/// # fn main() {
264/// let a: i8 = 1;
265/// let b = String::from("2");
266/// assert_fn_ok_ne_x!(f, a, b);
267///
268/// # let result = panic::catch_unwind(|| {
269/// // This will panic
270/// let a: i8 = 1;
271/// let b = String::from("1");
272/// assert_fn_ok_ne_x!(f, a, b);
273/// # });
274/// // assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`
275/// // https://docs.rs/assertables/9.7.0/assertables/macro.assert_fn_ok_ne_x.html
276/// // a_function label: `f`,
277/// // a_param label: `a`,
278/// // a_param debug: `1`,
279/// // b_expr label: `b`,
280/// // b_expr debug: `\"1\"`,
281/// // a: `\"1\"`,
282/// // b: `\"1\"`
283/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
284/// # let message = concat!(
285/// # "assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`\n",
286/// # "https://docs.rs/assertables/", env!("CARGO_PKG_VERSION"), "/assertables/macro.assert_fn_ok_ne_x.html\n",
287/// # " a_function label: `f`,\n",
288/// # " a_param label: `a`,\n",
289/// # " a_param debug: `1`,\n",
290/// # " b_expr label: `b`,\n",
291/// # " b_expr debug: `\"1\"`,\n",
292/// # " a: `\"1\"`,\n",
293/// # " b: `\"1\"`"
294/// # );
295/// # assert_eq!(actual, message);
296/// # }
297/// ```
298///
299/// # Module macros
300///
301/// * [`assert_fn_ok_ne_x`](macro@crate::assert_fn_ok_ne_x)
302/// * [`assert_fn_ok_ne_x_as_result`](macro@crate::assert_fn_ok_ne_x_as_result)
303/// * [`debug_assert_fn_ok_ne_x`](macro@crate::debug_assert_fn_ok_ne_x)
304///
305#[macro_export]
306macro_rules! assert_fn_ok_ne_x {
307
308 //// Arity 1
309
310 ($a_function:path, $a_param:expr, $b_expr:expr $(,)?) => {
311 match $crate::assert_fn_ok_ne_x_as_result!($a_function, $a_param, $b_expr) {
312 Ok(x) => x,
313 Err(err) => panic!("{}", err),
314 }
315 };
316
317 ($a_function:path, $a_param:expr, $b_expr:expr, $($message:tt)+) => {
318 match $crate::assert_fn_ok_ne_x_as_result!($a_function, $a_param, $b_expr) {
319 Ok(x) => x,
320 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
321 }
322 };
323
324 //// Arity 0
325
326 ($a_function:path, $b_expr:expr $(,)?) => {
327 match $crate::assert_fn_ok_ne_x_as_result!($a_function, $b_expr) {
328 Ok(x) => x,
329 Err(err) => panic!("{}", err),
330 }
331 };
332
333 ($a_function:path, $b_expr:expr, $($message:tt)+) => {
334 match $crate::assert_fn_ok_ne_x_as_result!($a_function, $b_expr) {
335 Ok(x) => x,
336 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
337 }
338 };
339}
340
341#[cfg(test)]
342mod test_assert_fn_ok_ne_x {
343 use std::panic;
344
345 mod arity_1 {
346 use super::*;
347
348 fn f(i: i8) -> Result<i8, i8> {
349 return Ok(i);
350 }
351
352 #[test]
353 fn ne() {
354 let a: i8 = 1;
355 let b: i8 = 2;
356 for _ in 0..1 {
357 let actual = assert_fn_ok_ne_x!(f, a, b);
358 assert_eq!(actual, 1);
359 }
360 }
361
362 #[test]
363 fn eq() {
364 let result = panic::catch_unwind(|| {
365 let a: i8 = 1;
366 let b: i8 = 1;
367 let _actual = assert_fn_ok_ne_x!(f, a, b);
368 });
369 let message = concat!(
370 "assertion failed: `assert_fn_ok_ne_x!(a_function, a_param, b_expr)`\n",
371 "https://docs.rs/assertables/",
372 env!("CARGO_PKG_VERSION"),
373 "/assertables/macro.assert_fn_ok_ne_x.html\n",
374 " a_function label: `f`,\n",
375 " a_param label: `a`,\n",
376 " a_param debug: `1`,\n",
377 " b_expr label: `b`,\n",
378 " b_expr debug: `1`,\n",
379 " a: `1`,\n",
380 " b: `1`"
381 );
382 assert_eq!(
383 result
384 .unwrap_err()
385 .downcast::<String>()
386 .unwrap()
387 .to_string(),
388 message
389 );
390 }
391 }
392
393 mod arity_0 {
394 use super::*;
395
396 fn f() -> Result<i8, i8> {
397 return Ok(1);
398 }
399
400 #[test]
401 fn ne() {
402 let b: i8 = 2;
403 for _ in 0..1 {
404 let actual = assert_fn_ok_ne_x!(f, b);
405 assert_eq!(actual, 1);
406 }
407 }
408
409 #[test]
410 fn eq() {
411 let result = panic::catch_unwind(|| {
412 let b: i8 = 1;
413 let _actual = assert_fn_ok_ne_x!(f, b);
414 });
415 let message = concat!(
416 "assertion failed: `assert_fn_ok_ne_x!(a_function, b_expr)`\n",
417 "https://docs.rs/assertables/",
418 env!("CARGO_PKG_VERSION"),
419 "/assertables/macro.assert_fn_ok_ne_x.html\n",
420 " a_function label: `f`,\n",
421 " b_expr label: `b`,\n",
422 " b_expr debug: `1`,\n",
423 " a: `1`,\n",
424 " b: `1`"
425 );
426 assert_eq!(
427 result
428 .unwrap_err()
429 .downcast::<String>()
430 .unwrap()
431 .to_string(),
432 message
433 );
434 }
435 }
436}
437
438/// Assert a function Ok(…) is not equal to an expression.
439///
440/// Pseudocode:<br>
441/// (a_function(a_param) ⇒ Ok(a) ⇒ a) ≠ expr
442///
443/// This macro provides the same statements as [`assert_fn_ok_ne_x`](macro.assert_fn_ok_ne_x.html),
444/// except this macro's statements are only enabled in non-optimized
445/// builds by default. An optimized build will not execute this macro's
446/// statements unless `-C debug-assertions` is passed to the compiler.
447///
448/// This macro is useful for checks that are too expensive to be present
449/// in a release build but may be helpful during development.
450///
451/// The result of expanding this macro is always type checked.
452///
453/// An unchecked assertion allows a program in an inconsistent state to
454/// keep running, which might have unexpected consequences but does not
455/// introduce unsafety as long as this only happens in safe code. The
456/// performance cost of assertions, however, is not measurable in general.
457/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
458/// after thorough profiling, and more importantly, only in safe code!
459///
460/// This macro is intended to work in a similar way to
461/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
462///
463/// # Module macros
464///
465/// * [`assert_fn_ok_ne_x`](macro@crate::assert_fn_ok_ne_x)
466/// * [`assert_fn_ok_ne_x`](macro@crate::assert_fn_ok_ne_x)
467/// * [`debug_assert_fn_ok_ne_x`](macro@crate::debug_assert_fn_ok_ne_x)
468///
469#[macro_export]
470macro_rules! debug_assert_fn_ok_ne_x {
471 ($($arg:tt)*) => {
472 if $crate::cfg!(debug_assertions) {
473 $crate::assert_fn_ok_ne_x!($($arg)*);
474 }
475 };
476}