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