pub(crate) mod guidance;
mod executable;
pub(crate) use executable::write_executable;
use std::process::Command;
use crate::interrupt;
pub(crate) fn scratch_worktree() -> tempfile::TempDir {
let worktree = tempfile::tempdir().unwrap();
assert!(
Command::new("git")
.args(["init", "-q"])
.arg(worktree.path())
.status()
.unwrap()
.success()
);
worktree
}
pub(crate) fn with_recorded_signal(test_name: &str, exercise: impl FnOnce(libc::c_int)) {
const TEST: &str = "THIRDSHIFT_TEST_SIGNAL_NAME";
const SIGNAL: &str = "THIRDSHIFT_TEST_SIGNAL";
if std::env::var(TEST).as_deref() == Ok(test_name) {
interrupt::install().unwrap();
exercise(std::env::var(SIGNAL).unwrap().parse().unwrap());
return;
}
for signal in [libc::SIGINT, libc::SIGTERM, libc::SIGHUP] {
let result = Command::new(std::env::current_exe().unwrap())
.args(["--exact", test_name, "--nocapture"])
.env(TEST, test_name)
.env(SIGNAL, signal.to_string())
.output()
.unwrap();
assert!(
result.status.success(),
"{test_name}, signal {signal}: {result:?}"
);
}
}
pub(crate) fn git_fault(name: &str, script: &str) -> Option<std::process::Output> {
if std::env::var("THIRDSHIFT_GIT_FAULT_TEST").as_deref() == Ok(name) {
return None;
}
let temp = tempfile::TempDir::new().unwrap();
let real_git = Command::new("sh")
.args(["-c", "command -v git"])
.output()
.unwrap();
assert!(real_git.status.success());
let shim = temp.path().join("git");
write_executable(
&shim,
&format!("#!/bin/sh\nset -e\n{script}\nexec \"$THIRDSHIFT_REAL_GIT\" \"$@\"\n"),
);
let search = std::env::var_os("PATH").unwrap();
let path = std::env::join_paths(
std::iter::once(temp.path().to_path_buf()).chain(std::env::split_paths(&search)),
)
.unwrap();
let output = Command::new(std::env::current_exe().unwrap())
.args(["--exact", name, "--nocapture"])
.env("PATH", path)
.env("THIRDSHIFT_GIT_FAULT_TEST", name)
.env(
"THIRDSHIFT_REAL_GIT",
String::from_utf8(real_git.stdout).unwrap().trim(),
)
.env("THIRDSHIFT_FAULT_MARKER", temp.path().join("fault"))
.output()
.unwrap();
assert!(output.status.success(), "{output:?}");
Some(output)
}