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}