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