use std::process::{Command, Stdio};
fn s3sync_command() -> Command {
let mut command = Command::new(env!("CARGO_BIN_EXE_s3sync"));
command.env_remove("AWS_PROFILE");
command.env_remove("AWS_ACCESS_KEY_ID");
command.env_remove("AWS_SECRET_ACCESS_KEY");
command.env_remove("AWS_SESSION_TOKEN");
command.env_remove("RUST_LOG");
command
}
fn run_with_closed_stdout(cmd: &mut Command) -> (Option<i32>, String) {
let (reader, writer) = std::io::pipe().expect("failed to create pipe");
drop(reader);
let output = cmd
.stdin(Stdio::null())
.stdout(Stdio::from(writer))
.stderr(Stdio::piped())
.output()
.expect("failed to spawn s3sync binary");
(
output.status.code(),
String::from_utf8_lossy(&output.stderr).to_string(),
)
}
fn assert_exits_zero_without_panic(code: Option<i32>, stderr: &str, what: &str) {
assert!(
!stderr.contains("panicked"),
"{what} must not panic on a closed stdout pipe; stderr: {stderr}"
);
assert_eq!(
code,
Some(0),
"{what} must exit 0 on a closed stdout pipe (None = killed by \
SIGPIPE); stderr: {stderr}"
);
}
#[test]
fn completion_script_with_closed_stdout_exits_zero() {
for shell in ["bash", "zsh", "fish"] {
let (code, stderr) =
run_with_closed_stdout(s3sync_command().args(["--auto-complete-shell", shell]));
assert_exits_zero_without_panic(code, &stderr, &format!("--auto-complete-shell {shell}"));
}
}
#[test]
fn help_and_version_with_closed_stdout_exit_zero() {
let (code, stderr) = run_with_closed_stdout(s3sync_command().arg("--help"));
assert_exits_zero_without_panic(code, &stderr, "--help");
let (code, stderr) = run_with_closed_stdout(s3sync_command().arg("--version"));
assert_exits_zero_without_panic(code, &stderr, "--version");
}