Skip to main content

assertables/
assert_ge.rs

1//! Assert an expression is greater than or equal to another.
2//!
3//! Pseudocode:<br>
4//! a ≥ b
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! let a = 2;
12//! let b = 1;
13//! assert_ge!(a, b);
14//! ```
15//!
16//! # Module macros
17//!
18//! * [`assert_ge`](macro@crate::assert_ge)
19//! * [`assert_ge_as_result`](macro@crate::assert_ge_as_result)
20//! * [`debug_assert_ge`](macro@crate::debug_assert_ge)
21
22/// Assert an expression is greater than or equal to another.
23///
24/// Pseudocode:<br>
25/// a ≥ b
26///
27/// * If true, return Result `Ok(())`.
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_ge`](macro@crate::assert_ge)
37/// * [`assert_ge_as_result`](macro@crate::assert_ge_as_result)
38/// * [`debug_assert_ge`](macro@crate::debug_assert_ge)
39///
40#[macro_export]
41macro_rules! assert_ge_as_result {
42    ($a:expr, $b:expr $(,)?) => {
43        match (&$a, &$b) {
44            (a, b) => {
45                if a >= b {
46                    Ok(())
47                } else {
48                    Err(format!(
49                        concat!(
50                            "assertion failed: `assert_ge!(a, b)`\n",
51                            "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
52                            " a label: `{}`,\n",
53                            " a debug: `{:?}`,\n",
54                            " b label: `{}`,\n",
55                            " b debug: `{:?}`",
56                        ),
57                        stringify!($a),
58                        a,
59                        stringify!($b),
60                        b
61                    ))
62                }
63            }
64        }
65    };
66}
67
68#[cfg(test)]
69mod test_assert_ge_as_result {
70    use std::sync::Once;
71
72    mod integer {
73        use super::*;
74
75        #[test]
76        fn gt() {
77            let a: i8 = 2;
78            let b: i8 = 1;
79            for _ in 0..1 {
80                let actual = assert_ge_as_result!(a, b);
81                assert_eq!(actual.unwrap(), ());
82            }
83        }
84
85        #[test]
86        fn gt_once() {
87            static A: Once = Once::new();
88            fn a() -> i8 {
89                if A.is_completed() {
90                    panic!("A.is_completed()")
91                } else {
92                    A.call_once(|| {})
93                }
94                2
95            }
96
97            static B: Once = Once::new();
98            fn b() -> i8 {
99                if B.is_completed() {
100                    panic!("B.is_completed()")
101                } else {
102                    B.call_once(|| {})
103                }
104                1
105            }
106
107            assert_eq!(A.is_completed(), false);
108            assert_eq!(B.is_completed(), false);
109            let result = assert_ge_as_result!(a(), b());
110            assert!(result.is_ok());
111            assert_eq!(A.is_completed(), true);
112            assert_eq!(B.is_completed(), true);
113        }
114
115        #[test]
116        fn eq() {
117            let a: i8 = 1;
118            let b: i8 = 1;
119            for _ in 0..1 {
120                let actual = assert_ge_as_result!(a, b);
121                assert_eq!(actual.unwrap(), ());
122            }
123        }
124
125        #[test]
126        fn eq_once() {
127            static A: Once = Once::new();
128            fn a() -> i8 {
129                if A.is_completed() {
130                    panic!("A.is_completed()")
131                } else {
132                    A.call_once(|| {})
133                }
134                1
135            }
136
137            static B: Once = Once::new();
138            fn b() -> i8 {
139                if B.is_completed() {
140                    panic!("B.is_completed()")
141                } else {
142                    B.call_once(|| {})
143                }
144                1
145            }
146
147            assert_eq!(A.is_completed(), false);
148            assert_eq!(B.is_completed(), false);
149            let result = assert_ge_as_result!(a(), b());
150            assert!(result.is_ok());
151            assert_eq!(A.is_completed(), true);
152            assert_eq!(B.is_completed(), true);
153        }
154
155        #[test]
156        fn lt() {
157            let a: i8 = 1;
158            let b: i8 = 2;
159            let actual = assert_ge_as_result!(a, b);
160            let message = concat!(
161                "assertion failed: `assert_ge!(a, b)`\n",
162                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
163                " a label: `a`,\n",
164                " a debug: `1`,\n",
165                " b label: `b`,\n",
166                " b debug: `2`",
167            );
168            assert_eq!(actual.unwrap_err(), message);
169        }
170    }
171
172    mod string {
173        use super::*;
174
175        #[test]
176        fn gt() {
177            let a: String = String::from("2");
178            let b: String = String::from("1");
179            for _ in 0..1 {
180                let actual = assert_ge_as_result!(a, b);
181                assert_eq!(actual.unwrap(), ());
182            }
183        }
184
185        #[test]
186        fn gt_once() {
187            static A: Once = Once::new();
188            fn a() -> String {
189                if A.is_completed() {
190                    panic!("A.is_completed()")
191                } else {
192                    A.call_once(|| {})
193                }
194                String::from("2")
195            }
196
197            static B: Once = Once::new();
198            fn b() -> String {
199                if B.is_completed() {
200                    panic!("B.is_completed()")
201                } else {
202                    B.call_once(|| {})
203                }
204                String::from("1")
205            }
206
207            assert_eq!(A.is_completed(), false);
208            assert_eq!(B.is_completed(), false);
209            let result = assert_ge_as_result!(a(), b());
210            assert!(result.is_ok());
211            assert_eq!(A.is_completed(), true);
212            assert_eq!(B.is_completed(), true);
213        }
214
215        #[test]
216        fn eq() {
217            let a: String = String::from("1");
218            let b: String = String::from("1");
219            for _ in 0..1 {
220                let actual = assert_ge_as_result!(a, b);
221                assert_eq!(actual.unwrap(), ());
222            }
223        }
224
225        #[test]
226        fn eq_once() {
227            static A: Once = Once::new();
228            fn a() -> String {
229                if A.is_completed() {
230                    panic!("A.is_completed()")
231                } else {
232                    A.call_once(|| {})
233                }
234                String::from("1")
235            }
236
237            static B: Once = Once::new();
238            fn b() -> String {
239                if B.is_completed() {
240                    panic!("B.is_completed()")
241                } else {
242                    B.call_once(|| {})
243                }
244                String::from("1")
245            }
246
247            assert_eq!(A.is_completed(), false);
248            assert_eq!(B.is_completed(), false);
249            let result = assert_ge_as_result!(a(), b());
250            assert!(result.is_ok());
251            assert_eq!(A.is_completed(), true);
252            assert_eq!(B.is_completed(), true);
253        }
254
255        #[test]
256        fn lt() {
257            let a: String = String::from("1");
258            let b: String = String::from("2");
259            let actual = assert_ge_as_result!(a, b);
260            let message = concat!(
261                "assertion failed: `assert_ge!(a, b)`\n",
262                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
263                " a label: `a`,\n",
264                " a debug: `\"1\"`,\n",
265                " b label: `b`,\n",
266                " b debug: `\"2\"`",
267            );
268            assert_eq!(actual.unwrap_err(), message);
269        }
270    }
271}
272
273/// Assert an expression is greater than or equal to another.
274///
275/// Pseudocode:<br>
276/// a ≥ b
277///
278/// * If true, return `()`.
279///
280/// * Otherwise, call [`panic!`] with a message and the values of the
281///   expressions with their debug representations.
282///
283/// # Examples
284///
285/// ```rust
286/// use assertables::*;
287/// # use std::panic;
288///
289/// # fn main() {
290/// let a = 2;
291/// let b = 1;
292/// assert_ge!(a, b);
293///
294/// # let result = panic::catch_unwind(|| {
295/// // This will panic
296/// let a = 1;
297/// let b = 2;
298/// assert_ge!(a, b);
299/// # });
300/// // assertion failed: `assert_ge!(a, b)`
301/// // https://docs.rs/assertables/…/assertables/macro.assert_ge.html
302/// //  a label: `a`,
303/// //  a debug: `1`,
304/// //  b label: `b`,
305/// //  b debug: `2`
306/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
307/// # let message = concat!(
308/// #     "assertion failed: `assert_ge!(a, b)`\n",
309/// #     "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
310/// #     " a label: `a`,\n",
311/// #     " a debug: `1`,\n",
312/// #     " b label: `b`,\n",
313/// #     " b debug: `2`",
314/// # );
315/// # assert_eq!(actual, message);
316/// # }
317/// ```
318///
319/// # Module macros
320///
321/// * [`assert_ge`](macro@crate::assert_ge)
322/// * [`assert_ge_as_result`](macro@crate::assert_ge_as_result)
323/// * [`debug_assert_ge`](macro@crate::debug_assert_ge)
324///
325#[macro_export]
326macro_rules! assert_ge {
327    ($a:expr, $b:expr $(,)?) => {
328        match $crate::assert_ge_as_result!($a, $b) {
329            Ok(()) => (),
330            Err(err) => panic!("{}", err),
331        }
332    };
333    ($a:expr, $b:expr, $($message:tt)+) => {
334        match $crate::assert_ge_as_result!($a, $b) {
335            Ok(()) => (),
336            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
337        }
338    };
339}
340
341#[cfg(test)]
342mod test_assert_ge {
343    use std::panic;
344
345    mod integer {
346        use super::*;
347
348        #[test]
349        fn gt() {
350            let a: i8 = 2;
351            let b: i8 = 1;
352            for _ in 0..1 {
353                let actual = assert_ge!(a, b);
354                let expect = ();
355                assert_eq!(actual, expect);
356            }
357        }
358
359        #[test]
360        fn eq() {
361            let a: i8 = 1;
362            let b: i8 = 1;
363            for _ in 0..1 {
364                let actual = assert_ge!(a, b);
365                let expect = ();
366                assert_eq!(actual, expect);
367            }
368        }
369
370        #[test]
371        fn lt() {
372            let a: i8 = 1;
373            let b: i8 = 2;
374            let result = panic::catch_unwind(|| {
375                let _actual = assert_ge!(a, b);
376            });
377            let message = concat!(
378                "assertion failed: `assert_ge!(a, b)`\n",
379                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
380                " a label: `a`,\n",
381                " a debug: `1`,\n",
382                " b label: `b`,\n",
383                " b debug: `2`",
384            );
385            assert_eq!(
386                result
387                    .unwrap_err()
388                    .downcast::<String>()
389                    .unwrap()
390                    .to_string(),
391                message
392            );
393        }
394    }
395
396    mod string {
397        use super::*;
398
399        #[test]
400        fn gt() {
401            let a: String = String::from("2");
402            let b: String = String::from("1");
403            for _ in 0..1 {
404                let actual = assert_ge!(a, b);
405                let expect = ();
406                assert_eq!(actual, expect);
407            }
408        }
409
410        #[test]
411        fn eq() {
412            let a: String = String::from("1");
413            let b: String = String::from("1");
414            for _ in 0..1 {
415                let actual = assert_ge!(a, b);
416                let expect = ();
417                assert_eq!(actual, expect);
418            }
419        }
420
421        #[test]
422        fn lt() {
423            let a: String = String::from("1");
424            let b: String = String::from("2");
425            let result = panic::catch_unwind(|| {
426                let _actual = assert_ge!(a, b);
427            });
428            let message = concat!(
429                "assertion failed: `assert_ge!(a, b)`\n",
430                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
431                " a label: `a`,\n",
432                " a debug: `\"1\"`,\n",
433                " b label: `b`,\n",
434                " b debug: `\"2\"`",
435            );
436            assert_eq!(
437                result
438                    .unwrap_err()
439                    .downcast::<String>()
440                    .unwrap()
441                    .to_string(),
442                message
443            );
444        }
445    }
446}
447
448/// Assert an expression is greater than or equal to another.
449///
450/// Pseudocode:<br>
451/// a ≥ b
452///
453/// This macro provides the same statements as [`assert_ge`](macro.assert_ge.html),
454/// except this macro's statements are only enabled in non-optimized
455/// builds by default. An optimized build will not execute this macro's
456/// statements unless `-C debug-assertions` is passed to the compiler.
457///
458/// This macro is useful for checks that are too expensive to be present
459/// in a release build but may be helpful during development.
460///
461/// The result of expanding this macro is always type checked.
462///
463/// An unchecked assertion allows a program in an inconsistent state to
464/// keep running, which might have unexpected consequences but does not
465/// introduce unsafety as long as this only happens in safe code. The
466/// performance cost of assertions, however, is not measurable in general.
467/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
468/// after thorough profiling, and more importantly, only in safe code!
469///
470/// This macro is intended to work in a similar way to
471/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
472///
473/// # Module macros
474///
475/// * [`assert_ge`](macro@crate::assert_ge)
476/// * [`assert_ge`](macro@crate::assert_ge)
477/// * [`debug_assert_ge`](macro@crate::debug_assert_ge)
478///
479#[macro_export]
480macro_rules! debug_assert_ge {
481    ($($arg:tt)*) => {
482        if cfg!(debug_assertions) {
483            $crate::assert_ge!($($arg)*);
484        }
485    };
486}
487
488#[cfg(test)]
489mod test_debug_assert_ge {
490    use std::panic;
491
492    mod integer {
493        use super::*;
494
495        #[test]
496        fn gt() {
497            let a: i8 = 2;
498            let b: i8 = 1;
499            for _ in 0..1 {
500                let _actual = debug_assert_ge!(a, b);
501                let _expect = ();
502                // assert_eq!(actual, expect);
503            }
504        }
505
506        #[test]
507        fn eq() {
508            let a: i8 = 1;
509            let b: i8 = 1;
510            for _ in 0..1 {
511                let _actual = debug_assert_ge!(a, b);
512                let _expect = ();
513                // assert_eq!(actual, expect);
514            }
515        }
516
517        #[test]
518        fn lt() {
519            let a: i8 = 1;
520            let b: i8 = 2;
521            let result = panic::catch_unwind(|| {
522                let _actual = debug_assert_ge!(a, b);
523            });
524            let message = concat!(
525                "assertion failed: `assert_ge!(a, b)`\n",
526                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
527                " a label: `a`,\n",
528                " a debug: `1`,\n",
529                " b label: `b`,\n",
530                " b debug: `2`",
531            );
532            assert_eq!(
533                result
534                    .unwrap_err()
535                    .downcast::<String>()
536                    .unwrap()
537                    .to_string(),
538                message
539            );
540        }
541    }
542
543    mod string {
544        use super::*;
545
546        #[test]
547        fn gt() {
548            let a: String = String::from("2");
549            let b: String = String::from("1");
550            for _ in 0..1 {
551                let _actual = debug_assert_ge!(a, b);
552                let _expect = ();
553                // assert_eq!(actual, expect);
554            }
555        }
556
557        #[test]
558        fn eq() {
559            let a: String = String::from("1");
560            let b: String = String::from("1");
561            for _ in 0..1 {
562                let _actual = debug_assert_ge!(a, b);
563                let _expect = ();
564                // assert_eq!(actual, expect);
565            }
566        }
567
568        #[test]
569        fn lt() {
570            let a: String = String::from("1");
571            let b: String = String::from("2");
572            let result = panic::catch_unwind(|| {
573                let _actual = debug_assert_ge!(a, b);
574            });
575            let message = concat!(
576                "assertion failed: `assert_ge!(a, b)`\n",
577                "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ge.html\n",
578                " a label: `a`,\n",
579                " a debug: `\"1\"`,\n",
580                " b label: `b`,\n",
581                " b debug: `\"2\"`",
582            );
583            assert_eq!(
584                result
585                    .unwrap_err()
586                    .downcast::<String>()
587                    .unwrap()
588                    .to_string(),
589                message
590            );
591        }
592    }
593}