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(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_ge!(a, b)`\n",
55 "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.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_ge!(a, b)`\n",
78 "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.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_ge!(a, b)`\n",
102 "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.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_ge_as_result {
125 use std::process::Command;
126
127 #[test]
128 fn gt() {
129 let mut a = Command::new("bin/exit-with-arg");
130 a.arg("2");
131 let mut b = Command::new("bin/exit-with-arg");
132 b.arg("1");
133 let actual = assert_status_code_value_ge_as_result!(a, b);
134 assert_eq!(actual.unwrap(), (2, 1));
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_ge_as_result!(a, b);
144 assert_eq!(actual.unwrap(), (1, 1));
145 }
146
147 #[test]
148 fn lt() {
149 let mut a = Command::new("bin/exit-with-arg");
150 a.arg("1");
151 let mut b = Command::new("bin/exit-with-arg");
152 b.arg("2");
153 let actual = assert_status_code_value_ge_as_result!(a, b);
154 let message = concat!(
155 "assertion failed: `assert_status_code_value_ge!(a, b)`\n",
156 "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.html\n",
157 " a label: `a`,\n",
158 " a debug: `\"bin/exit-with-arg\" \"1\"`,\n",
159 " a value: `1`,\n",
160 " b label: `b`,\n",
161 " b debug: `\"bin/exit-with-arg\" \"2\"`\n",
162 " b value: `2`"
163 );
164 assert_eq!(actual.unwrap_err(), message);
165 }
166}
167
168/// Assert a status code value is greater than or equal to another.
169///
170/// Pseudocode:<br>
171/// a ⇒ status ⇒ code ⇒ value ≥ b ⇒ status ⇒ code ⇒ value
172///
173/// * If true, return `(a value, b value)`.
174///
175/// * Otherwise, call [`panic!`] with a message and the values of the
176/// expressions with their debug representations.
177///
178/// # Examples
179///
180/// ```rust
181/// use assertables::*;
182/// use std::process::Command;
183/// # use std::panic;
184///
185/// # fn main() {
186/// let mut a = Command::new("bin/exit-with-arg"); a.arg("2");
187/// let mut b = Command::new("bin/exit-with-arg"); b.arg("1");
188/// assert_status_code_value_ge!(a, b);
189///
190/// # let result = panic::catch_unwind(|| {
191/// // This will panic
192/// let mut a = Command::new("bin/exit-with-arg"); a.arg("1");
193/// let mut b = Command::new("bin/exit-with-arg"); b.arg("2");
194/// assert_status_code_value_ge!(a, b);
195/// # });
196/// // assertion failed: `assert_status_code_value_ge!(a, b)`
197/// // https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.html
198/// // a label: `a`,
199/// // a debug: `\"bin/exit-with-arg\" \"1\"`,
200/// // a value: `1`",
201/// // b label: `b`,
202/// // b debug: `\"bin/exit-with-arg\" \"1\"`,
203/// // b value: `2`"
204/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
205/// # let message = concat!(
206/// # "assertion failed: `assert_status_code_value_ge!(a, b)`\n",
207/// # "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.html\n",
208/// # " a label: `a`,\n",
209/// # " a debug: `\"bin/exit-with-arg\" \"1\"`,\n",
210/// # " a value: `1`,\n",
211/// # " b label: `b`,\n",
212/// # " b debug: `\"bin/exit-with-arg\" \"2\"`\n",
213/// # " b value: `2`",
214/// # );
215/// # assert_eq!(actual, message);
216/// # }
217/// ```
218///
219/// # Module macros
220///
221/// * [`assert_status_code_value_ge`](macro@crate::assert_status_code_value_ge)
222/// * [`assert_status_code_value_ge_as_result`](macro@crate::assert_status_code_value_ge_as_result)
223/// * [`debug_assert_status_code_value_ge`](macro@crate::debug_assert_status_code_value_ge)
224///
225#[macro_export]
226macro_rules! assert_status_code_value_ge {
227 ($a_process:expr, $b_process:expr $(,)?) => {{
228 match $crate::assert_status_code_value_ge_as_result!($a_process, $b_process) {
229 Ok(x) => x,
230 Err(err) => panic!("{}", err),
231 }
232 }};
233 ($a_process:expr, $b_process:expr, $($message:tt)+) => {{
234 match $crate::assert_status_code_value_ge_as_result!($a_process, $b_process) {
235 Ok(x) => x,
236 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
237 }
238 }};
239}
240
241#[cfg(test)]
242mod test_assert_status_code_value_ge {
243 use std::panic;
244 use std::process::Command;
245
246 #[test]
247 fn gt() {
248 let mut a = Command::new("bin/exit-with-arg");
249 a.arg("2");
250 let mut b = Command::new("bin/exit-with-arg");
251 b.arg("1");
252 let actual = assert_status_code_value_ge!(a, b);
253 assert_eq!(actual, (2, 1));
254 }
255
256 #[test]
257 fn eq() {
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("1");
262 let actual = assert_status_code_value_ge!(a, b);
263 assert_eq!(actual, (1, 1));
264 }
265
266 #[test]
267 fn lt() {
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("2");
273 let _actual = assert_status_code_value_ge!(a, b);
274 });
275 let message = concat!(
276 "assertion failed: `assert_status_code_value_ge!(a, b)`\n",
277 "https://docs.rs/assertables/9.5.1/assertables/macro.assert_status_code_value_ge.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\" \"2\"`\n",
283 " b value: `2`"
284 );
285 assert_eq!(
286 result
287 .unwrap_err()
288 .downcast::<String>()
289 .unwrap()
290 .to_string(),
291 message
292 );
293 }
294}
295
296/// Assert a status code value is greater than or equal to another.
297///
298/// Pseudocode:<br>
299/// a ⇒ status ⇒ code ⇒ value ≥ b ⇒ status ⇒ code ⇒ value
300///
301/// This macro provides the same statements as [`assert_status_code_value_ge`](macro.assert_status_code_value_ge.html),
302/// except this macro's statements are only enabled in non-optimized
303/// builds by default. An optimized build will not execute this macro's
304/// statements unless `-C debug-assertions` is passed to the compiler.
305///
306/// This macro is useful for checks that are too expensive to be present
307/// in a release build but may be helpful during development.
308///
309/// The result of expanding this macro is always type checked.
310///
311/// An unchecked assertion allows a "bin/exit-with-arg" in an inconsistent state to
312/// keep running, which might have unexpected consequences but does not
313/// introduce unsafety as long as this only happens in safe code. The
314/// performance cost of assertions, however, is not measurable in general.
315/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
316/// after thorough profiling, and more importantly, only in safe code!
317///
318/// This macro is intended to work in a similar way to
319/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
320///
321/// # Module macros
322///
323/// * [`assert_status_code_value_ge`](macro@crate::assert_status_code_value_ge)
324/// * [`assert_status_code_value_ge`](macro@crate::assert_status_code_value_ge)
325/// * [`debug_assert_status_code_value_ge`](macro@crate::debug_assert_status_code_value_ge)
326///
327#[macro_export]
328macro_rules! debug_assert_status_code_value_ge {
329 ($($arg:tt)*) => {
330 if $crate::cfg!(debug_assertions) {
331 $crate::assert_status_code_value_ge!($($arg)*);
332 }
333 };
334}