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