assertables/
assert_lt.rs

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