Skip to main content

assertables/assert_fn_err/
assert_fn_err_lt.rs

1//! Assert a function Err(…) is less than another.
2//!
3//! Pseudocode:<br>
4//! (a_function(a_param) ⇒ Err(a) ⇒ a) < (b_function(b_param) ⇒ Err(b) ⇒ b)
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 = 10;
18//! let b: i8 = 20;
19//! assert_fn_err_lt!(f, a, f, b);
20//! ```
21//!
22//! # Module macros
23//!
24//! * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
25//! * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
26//! * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
27
28/// Assert a function error is less than another.
29///
30/// * If true, return Result `Ok(a)`.
31///
32/// * Otherwise, return Result `Err(message)`.
33///
34/// This macro is useful for runtime checks, such as checking parameters,
35/// or sanitizing inputs, or handling different results in different ways.
36///
37/// # Module macros
38///
39/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
40/// * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
41/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
42///
43#[macro_export]
44macro_rules! assert_fn_err_lt_as_result {
45
46    //// Arity 1
47
48    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {
49        match (&$a_function, &$a_param, &$b_function, &$b_param) {
50            (_a_function, a_param, _b_function, b_param) => {
51                match (
52                    $a_function($a_param),
53                    $b_function($b_param)
54                ) {
55                    (Err(a), Err(b)) => {
56                        if a < b {
57                            Ok((a, b))
58                        } else {
59                            Err(
60                                format!(
61                                    concat!(
62                                        "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
63                                        "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
64                                        " a_function label: `{}`,\n",
65                                        "    a_param label: `{}`,\n",
66                                        "    a_param debug: `{:?}`,\n",
67                                        " b_function label: `{}`,\n",
68                                        "    b_param label: `{}`,\n",
69                                        "    b_param debug: `{:?}`,\n",
70                                        "                a: `{:?}`,\n",
71                                        "                b: `{:?}`"
72                                    ),
73                                    stringify!($a_function),
74                                    stringify!($a_param),
75                                    a_param,
76                                    stringify!($b_function),
77                                    stringify!($b_param),
78                                    b_param,
79                                    a,
80                                    b
81                                )
82                            )
83                        }
84                    },
85                    (a, b) => {
86                        Err(
87                            format!(
88                                concat!(
89                                    "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
90                                    "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
91                                    " a_function label: `{}`,\n",
92                                    "    a_param label: `{}`,\n",
93                                    "    a_param debug: `{:?}`,\n",
94                                    " b_function label: `{}`,\n",
95                                    "    b_param label: `{}`,\n",
96                                    "    b_param debug: `{:?}`,\n",
97                                    "                a: `{:?}`,\n",
98                                    "                b: `{:?}`"
99                                ),
100                                stringify!($a_function),
101                                stringify!($a_param),
102                                a_param,
103                                stringify!($b_function),
104                                stringify!($b_param),
105                                b_param,
106                                a,
107                                b
108                            )
109                        )
110                    }
111                }
112            }
113        }
114    };
115
116    //// Arity 0
117
118    ($a_function:path, $b_function:path) => {
119        match (
120            $a_function(),
121            $b_function()
122        ) {
123            (Err(a), Err(b)) => {
124                if a < b {
125                    Ok((a, b))
126                } else {
127                    Err(
128                        format!(
129                            concat!(
130                                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
131                                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
132                                " a_function label: `{}`,\n",
133                                " b_function label: `{}`,\n",
134                                "                a: `{:?}`,\n",
135                                "                b: `{:?}`"
136                            ),
137                            stringify!($a_function),
138                            stringify!($b_function),
139                            a,
140                            b
141                        )
142                    )
143                }
144            },
145            (a, b) => {
146                Err(
147                    format!(
148                        concat!(
149                            "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
150                            "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
151                            " a_function label: `{}`,\n",
152                            " b_function label: `{}`,\n",
153                            "                a: `{:?}`,\n",
154                            "                b: `{:?}`"
155                        ),
156                        stringify!($a_function),
157                        stringify!($b_function),
158                        a,
159                        b
160                    )
161                )
162            }
163        }
164    };
165
166}
167
168#[cfg(test)]
169mod test_assert_fn_err_lt_as_result {
170    // use std::sync::Once;
171
172    mod arity_1 {
173
174        fn f(i: i8) -> Result<i8, i8> {
175            Err(i)
176        }
177
178        fn g(i: i8) -> Result<i8, i8> {
179            Err(i)
180        }
181
182        #[test]
183        fn lt() {
184            let a: i8 = 1;
185            let b: i8 = 2;
186            for _ in 0..1 {
187                let actual = assert_fn_err_lt_as_result!(f, a, g, b);
188                assert_eq!(actual.unwrap(), (1, 2));
189            }
190        }
191
192        #[test]
193        fn eq() {
194            let a: i8 = 1;
195            let b: i8 = 1;
196            let actual = assert_fn_err_lt_as_result!(f, a, g, b);
197            let message = concat!(
198                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
199                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
200                " a_function label: `f`,\n",
201                "    a_param label: `a`,\n",
202                "    a_param debug: `1`,\n",
203                " b_function label: `g`,\n",
204                "    b_param label: `b`,\n",
205                "    b_param debug: `1`,\n",
206                "                a: `1`,\n",
207                "                b: `1`"
208            );
209            assert_eq!(actual.unwrap_err(), message);
210        }
211
212        #[test]
213        fn gt() {
214            let a: i8 = 2;
215            let b: i8 = 1;
216            let actual = assert_fn_err_lt_as_result!(f, a, g, b);
217            let message = concat!(
218                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
219                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
220                " a_function label: `f`,\n",
221                "    a_param label: `a`,\n",
222                "    a_param debug: `2`,\n",
223                " b_function label: `g`,\n",
224                "    b_param label: `b`,\n",
225                "    b_param debug: `1`,\n",
226                "                a: `2`,\n",
227                "                b: `1`"
228            );
229            assert_eq!(actual.unwrap_err(), message);
230        }
231    }
232
233    mod arity_0 {
234
235        fn f() -> Result<i8, i8> {
236            Err(1)
237        }
238
239        fn g() -> Result<i8, i8> {
240            Err(2)
241        }
242
243        #[test]
244        fn lt() {
245            for _ in 0..1 {
246                let actual = assert_fn_err_lt_as_result!(f, g);
247                assert_eq!(actual.unwrap(), (1, 2));
248            }
249        }
250
251        #[test]
252        fn eq() {
253            let actual = assert_fn_err_lt_as_result!(f, f);
254            let message = concat!(
255                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
256                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
257                " a_function label: `f`,\n",
258                " b_function label: `f`,\n",
259                "                a: `1`,\n",
260                "                b: `1`"
261            );
262            assert_eq!(actual.unwrap_err(), message);
263        }
264
265        #[test]
266        fn gt() {
267            let actual = assert_fn_err_lt_as_result!(g, f);
268            let message = concat!(
269                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
270                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
271                " a_function label: `g`,\n",
272                " b_function label: `f`,\n",
273                "                a: `2`,\n",
274                "                b: `1`"
275            );
276            assert_eq!(actual.unwrap_err(), message);
277        }
278    }
279}
280
281/// Assert a function error is less than another.
282///
283/// * If true, return `(a, b)`.
284///
285/// * Otherwise, call [`panic!`] with a message and the values of the
286///   expressions with their debug representations.
287///
288/// # Examples
289///
290/// ```rust
291/// use assertables::*;
292/// # use std::panic;
293/// fn f(i: i8) -> Result<String, String> {
294///     match i {
295///         0..=9 => Ok(format!("{}", i)),
296///         _ => Err(format!("{:?} is out of range", i)),
297///     }
298/// }
299///
300/// # fn main() {
301/// let a: i8 = 10;
302/// let b: i8 = 20;
303/// assert_fn_err_lt!(f, a, f, b);
304///
305/// # let result = panic::catch_unwind(|| {
306/// // This will panic
307/// let a: i8 = 20;
308/// let b: i8 = 10;
309/// assert_fn_err_lt!(f, a, f, b);
310/// # });
311/// // assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`
312/// // https://docs.rs/assertables/…/assertables/macro.assert_fn_err_lt.html
313/// //  a_function label: `f`,
314/// //     a_param label: `a`,
315/// //     a_param debug: `20`,
316/// //  b_function label: `f`,
317/// //     b_param label: `b`,
318/// //     b_param debug: `10`,
319/// //                 a: `\"20 is out of range\"`,
320/// //                 b: `\"10 is out of range\"`
321/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
322/// # let message = concat!(
323/// #     "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
324/// #     "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
325/// #     " a_function label: `f`,\n",
326/// #     "    a_param label: `a`,\n",
327/// #     "    a_param debug: `20`,\n",
328/// #     " b_function label: `f`,\n",
329/// #     "    b_param label: `b`,\n",
330/// #     "    b_param debug: `10`,\n",
331/// #     "                a: `\"20 is out of range\"`,\n",
332/// #     "                b: `\"10 is out of range\"`"
333/// # );
334/// # assert_eq!(actual, message);
335/// # }
336/// ```
337///
338/// # Module macros
339///
340/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
341/// * [`assert_fn_err_lt_as_result`](macro@crate::assert_fn_err_lt_as_result)
342/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
343///
344#[macro_export]
345macro_rules! assert_fn_err_lt {
346
347    //// Arity 1
348
349    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr $(,)?) => {
350        match $crate::assert_fn_err_lt_as_result!($a_function, $a_param, $b_function, $b_param) {
351            Ok(x) => x,
352            Err(err) => panic!("{}", err),
353        }
354    };
355
356    ($a_function:path, $a_param:expr, $b_function:path, $b_param:expr, $($message:tt)+) => {
357        match $crate::assert_fn_err_lt_as_result!($a_function, $a_param, $b_function, $b_param) {
358            Ok(x) => x,
359            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
360        }
361    };
362
363    //// Arity 0
364
365    ($a_function:path, $b_function:path) => {
366        match $crate::assert_fn_err_lt_as_result!($a_function, $b_function) {
367            Ok(x) => x,
368            Err(err) => panic!("{}", err),
369        }
370    };
371
372    ($a_function:path, $b_function:path, $($message:tt)+) => {
373        match $crate::assert_fn_err_lt_as_result!($a_function, $b_function) {
374            Ok(x) => x,
375            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
376        }
377    };
378}
379
380#[cfg(test)]
381mod test_assert_fn_err_lt {
382    use std::panic;
383
384    mod arity_1 {
385        use super::*;
386
387        fn f(i: i8) -> Result<i8, i8> {
388            Err(i)
389        }
390
391        fn g(i: i8) -> Result<i8, i8> {
392            Err(i)
393        }
394
395        #[test]
396        fn lt() {
397            let a: i8 = 1;
398            let b: i8 = 2;
399            for _ in 0..1 {
400                let actual = assert_fn_err_lt!(f, a, g, b);
401                let expect = (1, 2);
402                assert_eq!(actual, expect);
403            }
404        }
405
406        #[test]
407        fn eq() {
408            let result = panic::catch_unwind(|| {
409                let a: i8 = 1;
410                let b: i8 = 1;
411                let _actual = assert_fn_err_lt!(f, a, g, b);
412            });
413            let message = concat!(
414                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
415                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
416                " a_function label: `f`,\n",
417                "    a_param label: `a`,\n",
418                "    a_param debug: `1`,\n",
419                " b_function label: `g`,\n",
420                "    b_param label: `b`,\n",
421                "    b_param debug: `1`,\n",
422                "                a: `1`,\n",
423                "                b: `1`"
424            );
425            assert_eq!(
426                result
427                    .unwrap_err()
428                    .downcast::<String>()
429                    .unwrap()
430                    .to_string(),
431                message
432            );
433        }
434
435        #[test]
436        fn gt() {
437            let result = panic::catch_unwind(|| {
438                let a: i8 = 2;
439                let b: i8 = 1;
440                let _actual = assert_fn_err_lt!(f, a, g, b);
441            });
442            let message = concat!(
443                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
444                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
445                " a_function label: `f`,\n",
446                "    a_param label: `a`,\n",
447                "    a_param debug: `2`,\n",
448                " b_function label: `g`,\n",
449                "    b_param label: `b`,\n",
450                "    b_param debug: `1`,\n",
451                "                a: `2`,\n",
452                "                b: `1`"
453            );
454            assert_eq!(
455                result
456                    .unwrap_err()
457                    .downcast::<String>()
458                    .unwrap()
459                    .to_string(),
460                message
461            );
462        }
463    }
464
465    mod arity_0 {
466        use super::*;
467
468        fn f() -> Result<i8, i8> {
469            Err(1)
470        }
471
472        fn g() -> Result<i8, i8> {
473            Err(2)
474        }
475
476        #[test]
477        fn lt() {
478            for _ in 0..1 {
479                let actual = assert_fn_err_lt!(f, g);
480                let expect = (1, 2);
481                assert_eq!(actual, expect);
482            }
483        }
484
485        #[test]
486        fn eq() {
487            let result = panic::catch_unwind(|| {
488                let _actual = assert_fn_err_lt!(f, f);
489            });
490            let message = concat!(
491                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
492                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
493                " a_function label: `f`,\n",
494                " b_function label: `f`,\n",
495                "                a: `1`,\n",
496                "                b: `1`"
497            );
498            assert_eq!(
499                result
500                    .unwrap_err()
501                    .downcast::<String>()
502                    .unwrap()
503                    .to_string(),
504                message
505            );
506        }
507
508        #[test]
509        fn gt() {
510            let result = panic::catch_unwind(|| {
511                let _actual = assert_fn_err_lt!(g, f);
512            });
513            let message = concat!(
514                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
515                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
516                " a_function label: `g`,\n",
517                " b_function label: `f`,\n",
518                "                a: `2`,\n",
519                "                b: `1`"
520            );
521            assert_eq!(
522                result
523                    .unwrap_err()
524                    .downcast::<String>()
525                    .unwrap()
526                    .to_string(),
527                message
528            );
529        }
530    }
531}
532
533/// Assert a function error is less than another.
534///
535/// This macro provides the same statements as [`assert_fn_err_lt`](macro.assert_fn_err_lt.html),
536/// except this macro's statements are only enabled in non-optimized
537/// builds by default. An optimized build will not execute this macro's
538/// statements unless `-C debug-assertions` is passed to the compiler.
539///
540/// This macro is useful for checks that are too expensive to be present
541/// in a release build but may be helpful during development.
542///
543/// The result of expanding this macro is always type checked.
544///
545/// An unchecked assertion allows a program in an inconsistent state to
546/// keep running, which might have unexpected consequences but does not
547/// introduce unsafety as long as this only happens in safe code. The
548/// performance cost of assertions, however, is not measurable in general.
549/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
550/// after thorough profiling, and more importantly, only in safe code!
551///
552/// This macro is intended to work in a similar way to
553/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
554///
555/// # Module macros
556///
557/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
558/// * [`assert_fn_err_lt`](macro@crate::assert_fn_err_lt)
559/// * [`debug_assert_fn_err_lt`](macro@crate::debug_assert_fn_err_lt)
560///
561#[macro_export]
562macro_rules! debug_assert_fn_err_lt {
563    ($($arg:tt)*) => {
564        if cfg!(debug_assertions) {
565            $crate::assert_fn_err_lt!($($arg)*);
566        }
567    };
568}
569
570#[cfg(test)]
571mod test_debug_assert_fn_err_lt {
572    use std::panic;
573
574    mod arity_1 {
575        use super::*;
576
577        fn f(i: i8) -> Result<i8, i8> {
578            Err(i)
579        }
580
581        fn g(i: i8) -> Result<i8, i8> {
582            Err(i)
583        }
584
585        #[test]
586        fn lt() {
587            let a: i8 = 1;
588            let b: i8 = 2;
589            for _ in 0..1 {
590                let _actual = debug_assert_fn_err_lt!(f, a, g, b);
591                let _expect = (1, 2);
592                // assert_eq!(actual, expect);
593            }
594        }
595
596        #[test]
597        fn eq() {
598            let result = panic::catch_unwind(|| {
599                let a: i8 = 1;
600                let b: i8 = 1;
601                let _actual = debug_assert_fn_err_lt!(f, a, g, b);
602            });
603            let message = concat!(
604                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
605                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
606                " a_function label: `f`,\n",
607                "    a_param label: `a`,\n",
608                "    a_param debug: `1`,\n",
609                " b_function label: `g`,\n",
610                "    b_param label: `b`,\n",
611                "    b_param debug: `1`,\n",
612                "                a: `1`,\n",
613                "                b: `1`"
614            );
615            assert_eq!(
616                result
617                    .unwrap_err()
618                    .downcast::<String>()
619                    .unwrap()
620                    .to_string(),
621                message
622            );
623        }
624
625        #[test]
626        fn gt() {
627            let result = panic::catch_unwind(|| {
628                let a: i8 = 2;
629                let b: i8 = 1;
630                let _actual = debug_assert_fn_err_lt!(f, a, g, b);
631            });
632            let message = concat!(
633                "assertion failed: `assert_fn_err_lt!(a_function, a_param, b_function, b_param)`\n",
634                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
635                " a_function label: `f`,\n",
636                "    a_param label: `a`,\n",
637                "    a_param debug: `2`,\n",
638                " b_function label: `g`,\n",
639                "    b_param label: `b`,\n",
640                "    b_param debug: `1`,\n",
641                "                a: `2`,\n",
642                "                b: `1`"
643            );
644            assert_eq!(
645                result
646                    .unwrap_err()
647                    .downcast::<String>()
648                    .unwrap()
649                    .to_string(),
650                message
651            );
652        }
653    }
654
655    mod arity_0 {
656        use super::*;
657
658        fn f() -> Result<i8, i8> {
659            Err(1)
660        }
661
662        fn g() -> Result<i8, i8> {
663            Err(2)
664        }
665
666        #[test]
667        fn lt() {
668            for _ in 0..1 {
669                let _actual = debug_assert_fn_err_lt!(f, g);
670                let _expect = (1, 2);
671                // assert_eq!(actual, expect);
672            }
673        }
674
675        #[test]
676        fn eq() {
677            let result = panic::catch_unwind(|| {
678                let _actual = debug_assert_fn_err_lt!(f, f);
679            });
680            let message = concat!(
681                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
682                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
683                " a_function label: `f`,\n",
684                " b_function label: `f`,\n",
685                "                a: `1`,\n",
686                "                b: `1`"
687            );
688            assert_eq!(
689                result
690                    .unwrap_err()
691                    .downcast::<String>()
692                    .unwrap()
693                    .to_string(),
694                message
695            );
696        }
697
698        #[test]
699        fn gt() {
700            let result = panic::catch_unwind(|| {
701                let _actual = debug_assert_fn_err_lt!(g, f);
702            });
703            let message = concat!(
704                "assertion failed: `assert_fn_err_lt!(a_function, b_function)`\n",
705                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_fn_err_lt.html\n",
706                " a_function label: `g`,\n",
707                " b_function label: `f`,\n",
708                "                a: `2`,\n",
709                "                b: `1`"
710            );
711            assert_eq!(
712                result
713                    .unwrap_err()
714                    .downcast::<String>()
715                    .unwrap()
716                    .to_string(),
717                message
718            );
719        }
720    }
721}