Add tests for TestDirExt

Some of these tests are ignored, because they trigger known TestDirExt
bugs. See #1140 for details.
This commit is contained in:
teor 2020-10-10 09:19:30 +10:00 committed by Deirdre Connolly
parent 3e897722a6
commit e3e85f5dbd
1 changed files with 169 additions and 0 deletions

169
zebra-test/tests/command.rs Normal file
View File

@ -0,0 +1,169 @@
#![allow(clippy::try_err)]
use std::{process::Command, time::Duration};
use color_eyre::eyre::Result;
use tempdir::TempDir;
use zebra_test::{command::TestDirExt, prelude::Stdio};
/// Returns true if `cmd` with `args` runs successfully.
///
/// On failure, prints an error message to stderr.
/// (This message is captured by the test runner, use `cargo test -- --nocapture` to see it.)
///
/// The command's stdout and stderr are ignored.
fn is_command_available(cmd: &str, args: &[&str]) -> bool {
let status = Command::new(cmd)
.args(args)
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
match status {
Err(e) => {
eprintln!(
"Skipping test because '{} {:?}' returned error {:?}",
cmd, args, e
);
false
}
Ok(status) if !status.success() => {
eprintln!(
"Skipping test because '{} {:?}' returned status {:?}",
cmd, args, status
);
false
}
_ => true,
}
}
/// Test if a process that keeps on producing lines of output is killed after the timeout.
#[test]
fn kill_on_timeout_output_continuous_lines() -> Result<()> {
zebra_test::init();
// Ideally, we'd want to use the 'yes' command here, but BSD yes treats
// every string as an argument to repeat - so we can't test if it is
// present on the system.
const TEST_CMD: &str = "hexdump";
// Skip the test if the test system does not have the command
if !is_command_available(TEST_CMD, &["/dev/null"]) {
return Ok(());
}
// Without '-v', hexdump hides duplicate lines. But we want duplicate lines
// in this test.
let mut child = TempDir::new("zebra_test")?
.spawn_child_with_command(TEST_CMD, &["-v", "/dev/zero"])?
.with_timeout(Duration::from_secs(2));
// We need to use expect_stdout, because wait_with_output ignores timeouts.
// We use a non-matching regex, to trigger the timeout.
assert!(child.expect_stdout("this regex should not match").is_err());
Ok(())
}
/// Test if the tests pass for a process that produces a single line of output,
/// then exits before the timeout.
//
// TODO: create a similar test that pauses after output
#[test]
fn finish_before_timeout_output_single_line() -> Result<()> {
zebra_test::init();
const TEST_CMD: &str = "echo";
// Skip the test if the test system does not have the command
if !is_command_available(TEST_CMD, &[]) {
return Ok(());
}
let mut child = TempDir::new("zebra_test")?
.spawn_child_with_command(TEST_CMD, &["zebra_test_output"])?
.with_timeout(Duration::from_secs(2));
// We need to use expect_stdout, because wait_with_output ignores timeouts.
// We use a non-matching regex, to trigger the timeout.
assert!(child.expect_stdout("this regex should not match").is_err());
Ok(())
}
/// Test if a process that keeps on producing output, but doesn't produce any newlines,
/// is killed after the timeout.
///
/// This test fails due to bugs in TestDirExt, see #1140 for details.
#[test]
#[ignore]
fn kill_on_timeout_continuous_output_no_newlines() -> Result<()> {
zebra_test::init();
const TEST_CMD: &str = "cat";
// Skip the test if the test system does not have the command
if !is_command_available(TEST_CMD, &["/dev/null"]) {
return Ok(());
}
let mut child = TempDir::new("zebra_test")?
.spawn_child_with_command(TEST_CMD, &["/dev/zero"])?
.with_timeout(Duration::from_secs(2));
// We need to use expect_stdout, because wait_with_output ignores timeouts.
// We use a non-matching regex, to trigger the timeout.
assert!(child.expect_stdout("this regex should not match").is_err());
Ok(())
}
/// Test if tests pass for a process that produces a small amount of output,
/// with no newlines, then exits before the timeout.
//
// TODO: create a similar test that pauses after output
#[test]
fn finish_before_timeout_short_output_no_newlines() -> Result<()> {
zebra_test::init();
const TEST_CMD: &str = "printf";
// Skip the test if the test system does not have the command
// The empty argument is required, because printf expects at least one argument.
if !is_command_available(TEST_CMD, &[""]) {
return Ok(());
}
let mut child = TempDir::new("zebra_test")?
.spawn_child_with_command(TEST_CMD, &["zebra_test_output"])?
.with_timeout(Duration::from_secs(2));
// We need to use expect_stdout, because wait_with_output ignores timeouts.
// We use a non-matching regex, to trigger the timeout.
assert!(child.expect_stdout("this regex should not match").is_err());
Ok(())
}
/// Test if the timeout works for a process that produces no output.
///
/// This test fails due to bugs in TestDirExt, see #1140 for details.
#[test]
#[ignore]
fn kill_on_timeout_no_output() -> Result<()> {
zebra_test::init();
const TEST_CMD: &str = "sleep";
// Skip the test if the test system does not have the command
if !is_command_available(TEST_CMD, &["0"]) {
return Ok(());
}
let mut child = TempDir::new("zebra_test")?
.spawn_child_with_command(TEST_CMD, &["120"])?
.with_timeout(Duration::from_secs(2));
// We need to use expect_stdout, because wait_with_output ignores timeouts.
// We use a non-matching regex, to trigger the timeout.
assert!(child.expect_stdout("this regex should not match").is_err());
Ok(())
}