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