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}