Skip to content

Commit 5e77f2b

Browse files
committed
Add test_ignore_and_pipefail() test suite over most entry points
1 parent f0c102c commit 5e77f2b

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

tests/test_macros.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,112 @@ fn test_pipe() {
160160
set_pipefail(true);
161161
}
162162

163+
#[test]
164+
fn test_ignore_and_pipefail() {
165+
struct TestCase {
166+
/// Run the test case, returning whether the result `.is_ok()`.
167+
code: fn() -> bool,
168+
/// Stringified version of `code`, for identifying assertion failures.
169+
code_str: &'static str,
170+
/// Do we expect `.is_ok()` when pipefail is on?
171+
expected_ok_pipefail_on: bool,
172+
/// Do we expect `.is_ok()` when pipefail is off?
173+
expected_ok_pipefail_off: bool,
174+
}
175+
/// Make a function for [TestCase::code].
176+
///
177+
/// Usage: `code!((macro!(command)).extra)`
178+
/// - `(macro!(command)).extra` is an expression of type CmdResult
179+
macro_rules! code {
180+
(($macro:tt $bang:tt ($($command:tt)+)) $($after:tt)*) => {
181+
|| $macro$bang($($command)+)$($after)*.is_ok()
182+
};
183+
}
184+
/// Make a string for [TestCase::code_str].
185+
///
186+
/// Usage: `code_str!((macro!(command)).extra)`
187+
/// - `(macro!(command)).extra` is an expression of type CmdResult
188+
macro_rules! code_str {
189+
(($macro:tt $bang:tt ($($command:tt)+)) $($after:tt)*) => {
190+
stringify!($macro$bang($($command)+)$($after)*.is_ok())
191+
};
192+
}
193+
/// Make a [TestCase].
194+
/// Usage: `test_case!(true/false, true/false, (macro!(command)).extra)`
195+
/// - the first `true/false` is TestCase::expected_ok_pipefail_on
196+
/// - the second `true/false` is TestCase::expected_ok_pipefail_off
197+
/// - `(macro!(command)).extra` is an expression of type CmdResult
198+
macro_rules! test_case {
199+
($expected_ok_pipefail_on:expr, $expected_ok_pipefail_off:expr, ($macro:tt $bang:tt ($($command:tt)+)) $($after:tt)*) => {
200+
TestCase {
201+
code: code!(($macro $bang ($($command)+)) $($after)*),
202+
code_str: code_str!(($macro $bang ($($command)+)) $($after)*),
203+
expected_ok_pipefail_on: $expected_ok_pipefail_on,
204+
expected_ok_pipefail_off: $expected_ok_pipefail_off,
205+
}
206+
};
207+
}
208+
/// Generate test cases for the given entry point.
209+
/// For each test case, every entry point should yield the same results.
210+
macro_rules! test_cases_for_entry_point {
211+
(($macro:tt $bang:tt (...)) $($after:tt)*) => {
212+
&[
213+
// Use result of last command in pipeline, if all others exit successfully.
214+
test_case!(true, true, ($macro $bang (true)) $($after)*),
215+
test_case!(false, false, ($macro $bang (false)) $($after)*),
216+
test_case!(true, true, ($macro $bang (true | true)) $($after)*),
217+
test_case!(false, false, ($macro $bang (true | false)) $($after)*),
218+
// Use failure of other commands, if pipefail is on.
219+
test_case!(false, true, ($macro $bang (false | true)) $($after)*),
220+
// Use failure of last command in pipeline.
221+
test_case!(false, false, ($macro $bang (false | false)) $($after)*),
222+
// Ignore all failures, when using `ignore` command.
223+
test_case!(true, true, ($macro $bang (ignore true)) $($after)*),
224+
test_case!(true, true, ($macro $bang (ignore false)) $($after)*),
225+
test_case!(true, true, ($macro $bang (ignore true | true)) $($after)*),
226+
test_case!(true, true, ($macro $bang (ignore true | false)) $($after)*),
227+
test_case!(true, true, ($macro $bang (ignore false | true)) $($after)*),
228+
test_case!(true, true, ($macro $bang (ignore false | false)) $($after)*),
229+
]
230+
};
231+
}
232+
233+
let test_cases: &[&[TestCase]] = &[
234+
test_cases_for_entry_point!((run_cmd!(...))),
235+
test_cases_for_entry_point!((run_fun!(...)).map(|_stdout| ())),
236+
test_cases_for_entry_point!((spawn!(...)).unwrap().wait()),
237+
test_cases_for_entry_point!((spawn_with_output!(...)).unwrap().wait_with_all().0),
238+
test_cases_for_entry_point!((spawn_with_output!(...))
239+
.unwrap()
240+
.wait_with_output()
241+
.map(|_stdout| ())),
242+
test_cases_for_entry_point!((spawn_with_output!(...))
243+
.unwrap()
244+
.wait_with_raw_output(&mut vec![])),
245+
// FIXME: wait_with_pipe() is currently busted
246+
// test_cases_for_entry_point!((spawn_with_output!(...))
247+
// .unwrap()
248+
// .wait_with_pipe(&mut |_stdout| {})),
249+
];
250+
251+
for case in test_cases.iter().flat_map(|items| items.iter()) {
252+
assert_eq!(
253+
(case.code)(),
254+
case.expected_ok_pipefail_on,
255+
"{} when pipefail is on",
256+
case.code_str
257+
);
258+
set_pipefail(false);
259+
assert_eq!(
260+
(case.code)(),
261+
case.expected_ok_pipefail_off,
262+
"{} when pipefail is off",
263+
case.code_str
264+
);
265+
set_pipefail(true);
266+
}
267+
}
268+
163269
#[test]
164270
/// ```compile_fail
165271
/// run_cmd!(ls > >&1).unwrap();

0 commit comments

Comments
 (0)