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.5.3/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
72 #[test]
73 fn lt() {
74 let a: i8 = 1;
75 let b: i8 = 2;
76 let actual = assert_lt_as_result!(a, b);
77 assert_eq!(actual.unwrap(), ());
78 }
79
80 #[test]
81 fn eq() {
82 let a: i8 = 1;
83 let b: i8 = 1;
84 let actual = assert_lt_as_result!(a, b);
85 let message = concat!(
86 "assertion failed: `assert_lt!(a, b)`\n",
87 "https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html\n",
88 " a label: `a`,\n",
89 " a debug: `1`,\n",
90 " b label: `b`,\n",
91 " b debug: `1`",
92 );
93 assert_eq!(actual.unwrap_err(), message);
94 }
95
96 #[test]
97 fn gt() {
98 let a: i8 = 2;
99 let b: i8 = 1;
100 let actual = assert_lt_as_result!(a, b);
101 let message = concat!(
102 "assertion failed: `assert_lt!(a, b)`\n",
103 "https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html\n",
104 " a label: `a`,\n",
105 " a debug: `2`,\n",
106 " b label: `b`,\n",
107 " b debug: `1`",
108 );
109 assert_eq!(actual.unwrap_err(), message);
110 }
111
112 use std::sync::Once;
113 #[test]
114 fn once() {
115
116 static A: Once = Once::new();
117 fn a() -> i8 {
118 if A.is_completed() { panic!("A.is_completed()") } else { A.call_once(|| {}) }
119 1
120 }
121
122 static B: Once = Once::new();
123 fn b() -> i8 {
124 if B.is_completed() { panic!("B.is_completed()") } else { B.call_once(|| {}) }
125 2
126 }
127
128 assert_eq!(A.is_completed(), false);
129 assert_eq!(B.is_completed(), false);
130 let result = assert_lt_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}
137
138/// Assert an expression is less than another.
139///
140/// Pseudocode:<br>
141/// a < b
142///
143/// * If true, return `()`.
144///
145/// * Otherwise, call [`panic!`] with a message and the values of the
146/// expressions with their debug representations.
147///
148/// # Examples
149///
150/// ```rust
151/// use assertables::*;
152/// # use std::panic;
153///
154/// # fn main() {
155/// let a = 1;
156/// let b = 2;
157/// assert_lt!(a, b);
158///
159/// # let result = panic::catch_unwind(|| {
160/// // This will panic
161/// let a = 2;
162/// let b = 1;
163/// assert_lt!(a, b);
164/// # });
165/// // assertion failed: `assert_lt!(a, b)`
166/// // https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html
167/// // a label: `a`,
168/// // a debug: `2`,
169/// // b label: `b`,
170/// // b debug: `1`
171/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
172/// # let message = concat!(
173/// # "assertion failed: `assert_lt!(a, b)`\n",
174/// # "https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html\n",
175/// # " a label: `a`,\n",
176/// # " a debug: `2`,\n",
177/// # " b label: `b`,\n",
178/// # " b debug: `1`",
179/// # );
180/// # assert_eq!(actual, message);
181/// # }
182/// ```
183///
184/// # Module macros
185///
186/// * [`assert_lt`](macro@crate::assert_lt)
187/// * [`assert_lt_as_result`](macro@crate::assert_lt_as_result)
188/// * [`debug_assert_lt`](macro@crate::debug_assert_lt)
189///
190#[macro_export]
191macro_rules! assert_lt {
192 ($a:expr, $b:expr $(,)?) => {{
193 match $crate::assert_lt_as_result!($a, $b) {
194 Ok(()) => (),
195 Err(err) => panic!("{}", err),
196 }
197 }};
198 ($a:expr, $b:expr, $($message:tt)+) => {{
199 match $crate::assert_lt_as_result!($a, $b) {
200 Ok(()) => (),
201 Err(err) => panic!("{}\n{}", format_args!($($message)+), err)
202 }
203 }};
204}
205
206#[cfg(test)]
207mod test_assert_lt {
208 use std::panic;
209
210 #[test]
211 fn lt() {
212 let a: i8 = 1;
213 let b: i8 = 2;
214 let actual = assert_lt!(a, b);
215 assert_eq!(actual, ());
216 }
217
218 #[test]
219 fn eq() {
220 let a: i8 = 1;
221 let b: i8 = 1;
222 let result = panic::catch_unwind(|| {
223 let _actual = assert_lt!(a, b);
224 });
225 let message = concat!(
226 "assertion failed: `assert_lt!(a, b)`\n",
227 "https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html\n",
228 " a label: `a`,\n",
229 " a debug: `1`,\n",
230 " b label: `b`,\n",
231 " b debug: `1`",
232 );
233 assert_eq!(
234 result
235 .unwrap_err()
236 .downcast::<String>()
237 .unwrap()
238 .to_string(),
239 message
240 );
241 }
242
243 #[test]
244 fn gt() {
245 let a: i8 = 2;
246 let b: i8 = 1;
247 let result = panic::catch_unwind(|| {
248 let _actual = assert_lt!(a, b);
249 });
250 let message = concat!(
251 "assertion failed: `assert_lt!(a, b)`\n",
252 "https://docs.rs/assertables/9.5.3/assertables/macro.assert_lt.html\n",
253 " a label: `a`,\n",
254 " a debug: `2`,\n",
255 " b label: `b`,\n",
256 " b debug: `1`",
257 );
258 assert_eq!(
259 result
260 .unwrap_err()
261 .downcast::<String>()
262 .unwrap()
263 .to_string(),
264 message
265 );
266 }
267}
268
269/// Assert an expression is less than another.
270///
271/// Pseudocode:<br>
272/// a < b
273///
274/// This macro provides the same statements as [`assert_lt`](macro.assert_lt.html),
275/// except this macro's statements are only enabled in non-optimized
276/// builds by default. An optimized build will not execute this macro's
277/// statements unless `-C debug-assertions` is passed to the compiler.
278///
279/// This macro is useful for checks that are too expensive to be present
280/// in a release build but may be helpful during development.
281///
282/// The result of expanding this macro is always type checked.
283///
284/// An unchecked assertion allows a program in an inconsistent state to
285/// keep running, which might have unexpected consequences but does not
286/// introduce unsafety as long as this only happens in safe code. The
287/// performance cost of assertions, however, is not measurable in general.
288/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
289/// after thorough profiling, and more importantly, only in safe code!
290///
291/// This macro is intended to work in a similar way to
292/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
293///
294/// # Module macros
295///
296/// * [`assert_lt`](macro@crate::assert_lt)
297/// * [`assert_lt`](macro@crate::assert_lt)
298/// * [`debug_assert_lt`](macro@crate::debug_assert_lt)
299///
300#[macro_export]
301macro_rules! debug_assert_lt {
302 ($($arg:tt)*) => {
303 if $crate::cfg!(debug_assertions) {
304 $crate::assert_lt!($($arg)*);
305 }
306 };
307}