100 lines
2.9 KiB
Rust
100 lines
2.9 KiB
Rust
// what a command reports and how it exits, including when the write fails.
|
|
mod support;
|
|
|
|
use std::fs;
|
|
use support::Case;
|
|
|
|
#[test]
|
|
fn findings_are_reported_through_the_exit_code() {
|
|
let case = Case::new("findings");
|
|
case.write("loose.txt", b"x\n");
|
|
|
|
case.ahab(&["link", "check"]).ok();
|
|
case.ahab(&["link", "check", "--exit-code"]).code_is(4);
|
|
}
|
|
|
|
#[test]
|
|
fn an_argument_error_exits_two() {
|
|
let case = Case::new("usage");
|
|
|
|
case.ahab(&["link", "restore"]).code_is(2);
|
|
case.ahab(&["link", "restore", "--all", "some/path"])
|
|
.code_is(2);
|
|
case.ahab(&["postgres", "dump", "-F", "directory", "-z", "d"])
|
|
.code_is(2);
|
|
case.ahab(&["nonsense"]).code_is(2);
|
|
}
|
|
|
|
#[test]
|
|
fn a_write_that_cannot_be_delivered_is_a_failure_rather_than_a_success() {
|
|
let case = Case::new("devfull");
|
|
for n in 0..200 {
|
|
case.write(&format!("file-{n}.txt"), b"x\n");
|
|
}
|
|
|
|
// /dev/full accepts the open and fails the write. exiting 0 there would
|
|
// report a listing that was never delivered
|
|
let Ok(full) = fs::File::create("/dev/full") else {
|
|
eprintln!("skipped: this system has no /dev/full to fail a write against");
|
|
return;
|
|
};
|
|
|
|
let out = std::process::Command::new(env!("CARGO_BIN_EXE_ahab"))
|
|
.current_dir(&case.repo)
|
|
.env("XDG_DATA_HOME", case.repo.join("../xdg"))
|
|
.args(["link", "check", "--exit-code", "--porcelain"])
|
|
.stdout(full)
|
|
.output()
|
|
.expect("running ahab");
|
|
|
|
assert_eq!(out.status.code(), Some(1), "{:?}", out.status);
|
|
assert!(
|
|
String::from_utf8_lossy(&out.stderr).contains("writing to stdout failed"),
|
|
"{}",
|
|
String::from_utf8_lossy(&out.stderr)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn every_named_path_is_moved_even_when_the_reader_leaves() {
|
|
let case = Case::new("partial");
|
|
for name in ["a.env", "b.env", "c.env"] {
|
|
case.write(name, b"x\n");
|
|
}
|
|
case.gitignore("a.env\nb.env\nc.env\n");
|
|
|
|
// a closed stdout must stop the writing, not the moving: the command had
|
|
// planned to move all three and reported success for doing so
|
|
let run = case.ahab(&["link", "add", "a.env", "b.env", "c.env"]);
|
|
run.ok();
|
|
|
|
for name in ["a.env", "b.env", "c.env"] {
|
|
assert!(case.is_symlink(name), "{name} was left behind");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn quiet_keeps_the_reason_a_path_failed() {
|
|
let case = Case::new("quiet");
|
|
case.write("ok.env", b"x\n");
|
|
case.gitignore("ok.env\n");
|
|
|
|
let run = case.ahab(&["-q", "link", "add", "ok.env", "missing.env"]);
|
|
run.failed()
|
|
.says("1 of 2 paths failed")
|
|
// the line saying *which* and *why* is a result, not progress
|
|
.says("missing.env");
|
|
}
|
|
|
|
#[test]
|
|
fn a_dry_run_changes_nothing_on_disk() {
|
|
let case = Case::new("dryrun");
|
|
case.write(".env", b"SECRET=1\n");
|
|
case.gitignore(".env\n");
|
|
|
|
case.ahab(&["--dry-run", "link", "add", ".env"]).ok();
|
|
|
|
assert!(!case.is_symlink(".env"));
|
|
assert!(!case.store.join(".env").exists());
|
|
}
|