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(format!(
52 concat!(
53 "assertion failed: `assert_command_stderr_ne_x!(command, expr)`\n",
54 "https://docs.rs/assertables/",
55 env!("CARGO_PKG_VERSION"),
56 "/assertables/macro.assert_command_stderr_ne_x.html\n",
57 " command label: `{}`,\n",
58 " command debug: `{:?}`,\n",
59 " command value: `{:?}`,\n",
60 " expr label: `{}`,\n",
61 " expr debug: `{:?}`,\n",
62 " expr value: `{:?}`"
63 ),
64 stringify!($a_command),
65 $a_command,
66 a,
67 stringify!($b_expr),
68 $b_expr,
69 b_expr
70 ))
71 }
72 }
73 (a, b) => Err(format!(
74 concat!(
75 "assertion failed: `assert_command_stderr_ne_x!(command, expr)`\n",
76 "https://docs.rs/assertables/",
77 env!("CARGO_PKG_VERSION"),
78 "/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#[cfg(test)]
98mod test_assert_command_stderr_ne_x_as_result {
99 use std::process::Command;
100 use std::sync::Once;
101
102 #[test]
103 fn lt() {
104 let mut a = Command::new("bin/printf-stderr");
105 a.args(["%s", "alfa"]);
106 let b = vec![b'z', b'z'];
107 for _ in 0..1 {
108 let actual = assert_command_stderr_ne_x_as_result!(a, b);
109 assert_eq!(actual.unwrap(), vec![b'a', b'l', b'f', b'a']);
110 }
111 }
112
113 #[test]
114 fn lt_once() {
115 static A: Once = Once::new();
116 fn a() -> Command {
117 if A.is_completed() {
118 panic!("A.is_completed()")
119 } else {
120 A.call_once(|| {})
121 }
122 let mut a = Command::new("bin/printf-stderr");
123 a.args(["%s", "alfa"]);
124 a
125 }
126
127 static B: Once = Once::new();
128 fn b() -> Vec<u8> {
129 if B.is_completed() {
130 panic!("B.is_completed()")
131 } else {
132 B.call_once(|| {})
133 }
134 vec![b'z', b'z']
135 }
136
137 assert_eq!(A.is_completed(), false);
138 assert_eq!(B.is_completed(), false);
139 let result = assert_command_stderr_ne_x_as_result!(a(), b());
140 assert!(result.is_ok());
141 assert_eq!(A.is_completed(), true);
142 assert_eq!(B.is_completed(), true);
143 }
144
145 #[test]
146 fn gt() {
147 let mut a = Command::new("bin/printf-stderr");
148 a.args(["%s", "alfa"]);
149 let b = vec![b'a', b'a'];
150 for _ in 0..1 {
151 let actual = assert_command_stderr_ne_x_as_result!(a, b);
152 assert_eq!(actual.unwrap(), vec![b'a', b'l', b'f', b'a']);
153 }
154 }
155
156 #[test]
157 fn gt_once() {
158 static A: Once = Once::new();
159 fn a() -> Command {
160 if A.is_completed() {
161 panic!("A.is_completed()")
162 } else {
163 A.call_once(|| {})
164 }
165 let mut a = Command::new("bin/printf-stderr");
166 a.args(["%s", "alfa"]);
167 a
168 }
169
170 static B: Once = Once::new();
171 fn b() -> Vec<u8> {
172 if B.is_completed() {
173 panic!("B.is_completed()")
174 } else {
175 B.call_once(|| {})
176 }
177 vec![b'a', b'a']
178 }
179
180 assert_eq!(A.is_completed(), false);
181 assert_eq!(B.is_completed(), false);
182 let result = assert_command_stderr_ne_x_as_result!(a(), b());
183 assert!(result.is_ok());
184 assert_eq!(A.is_completed(), true);
185 assert_eq!(B.is_completed(), true);
186 }
187
188 #[test]
189 fn eq() {
190 let mut a = Command::new("bin/printf-stderr");
191 a.args(["%s", "alfa"]);
192 let b = vec![b'a', b'l', b'f', b'a'];
193 let actual = assert_command_stderr_ne_x_as_result!(a, b);
194 let message = concat!(
195 "assertion failed: `assert_command_stderr_ne_x!(command, expr)`\n",
196 "https://docs.rs/assertables/",
197 env!("CARGO_PKG_VERSION"),
198 "/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.7.0/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/", env!("CARGO_PKG_VERSION"), "/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/",
323 env!("CARGO_PKG_VERSION"),
324 "/assertables/macro.assert_command_stderr_ne_x.html\n",
325 " command label: `a`,\n",
326 " command debug: `\"bin/printf-stderr\" \"%s\" \"alfa\"`,\n",
327 " command value: `[97, 108, 102, 97]`,\n",
328 " expr label: `b`,\n",
329 " expr debug: `[97, 108, 102, 97]`,\n",
330 " expr value: `[97, 108, 102, 97]`"
331 );
332 assert_eq!(
333 result
334 .unwrap_err()
335 .downcast::<String>()
336 .unwrap()
337 .to_string(),
338 message
339 );
340 }
341}
342
343/// Assert a command stderr string is not equal to an expression.
344///
345/// Pseudocode:<br>
346/// (command ⇒ stderr) = (expr into string)
347///
348/// This macro provides the same statements as [`assert_command_stderr_ne_x`](macro.assert_command_stderr_ne_x.html),
349/// except this macro's statements are only enabled in non-optimized
350/// builds by default. An optimized build will not execute this macro's
351/// statements unless `-C debug-assertions` is passed to the compiler.
352///
353/// This macro is useful for checks that are too expensive to be present
354/// in a release build but may be helpful during development.
355///
356/// The result of expanding this macro is always type checked.
357///
358/// An unchecked assertion allows a program in an inconsistent state to
359/// keep running, which might have unexpected consequences but does not
360/// introduce unsafety as long as this only happens in safe code. The
361/// performance cost of assertions, however, is not measurable in general.
362/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
363/// after thorough profiling, and more importantly, only in safe code!
364///
365/// This macro is intended to work in a similar way to
366/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
367///
368/// # Module macros
369///
370/// * [`assert_command_stderr_ne_x`](macro@crate::assert_command_stderr_ne_x)
371/// * [`assert_command_stderr_ne_x`](macro@crate::assert_command_stderr_ne_x)
372/// * [`debug_assert_command_stderr_ne_x`](macro@crate::debug_assert_command_stderr_ne_x)
373///
374#[macro_export]
375macro_rules! debug_assert_command_stderr_ne_x {
376 ($($arg:tt)*) => {
377 if $crate::cfg!(debug_assertions) {
378 $crate::assert_command_stderr_ne_x!($($arg)*);
379 }
380 };
381}