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