assertables/assert_status/
assert_status_code_value_ge.rs

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