assertables/assert_status/
assert_status_code_value_lt.rs

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