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