mod common;
fn write_config(workspace: &std::path::Path, body: &str) {
std::fs::write(workspace.join(".atomwrite.toml"), body).expect("write .atomwrite.toml");
}
fn has_bak_file(dir: &std::path::Path) -> bool {
std::fs::read_dir(dir)
.expect("read dir")
.filter_map(Result::ok)
.any(|e| e.file_name().to_string_lossy().contains(".bak."))
}
fn count_bak_files(dir: &std::path::Path) -> usize {
std::fs::read_dir(dir)
.expect("read dir")
.filter_map(Result::ok)
.filter(|e| e.file_name().to_string_lossy().contains(".bak."))
.count()
}
#[test]
fn config_defaults_backup_false_is_honored_without_flags() {
let dir = tempfile::tempdir().expect("tempdir");
write_config(dir.path(), "[defaults]\nbackup = false\nretention = 2\n");
let path = common::create_test_file(dir.path(), "f.txt", "bye\n");
let output = common::atomwrite()
.env_remove("ATOMWRITE_BACKUP")
.args([
"--workspace",
dir.path().to_str().unwrap(),
"delete",
])
.arg(&path)
.output()
.expect("run");
assert!(output.status.success());
assert!(
!has_bak_file(dir.path()),
"[defaults].backup = false must be honored when no backup flag is passed"
);
}
#[test]
fn explicit_backup_flag_overrides_config_defaults_backup_false() {
let dir = tempfile::tempdir().expect("tempdir");
write_config(dir.path(), "[defaults]\nbackup = false\nretention = 2\n");
let path = common::create_test_file(dir.path(), "f.txt", "bye\n");
let output = common::atomwrite()
.env_remove("ATOMWRITE_BACKUP")
.args([
"--workspace",
dir.path().to_str().unwrap(),
"delete",
"--backup",
])
.arg(&path)
.output()
.expect("run");
assert!(output.status.success());
assert!(
has_bak_file(dir.path()),
"explicit --backup must override [defaults].backup = false"
);
}
#[test]
fn env_atomwrite_backup_zero_does_not_override_explicit_backup_flag() {
let dir = tempfile::tempdir().expect("tempdir");
let path = common::create_test_file(dir.path(), "f.txt", "bye\n");
let output = common::atomwrite()
.env("ATOMWRITE_BACKUP", "0")
.args([
"--workspace",
dir.path().to_str().unwrap(),
"delete",
"--backup",
])
.arg(&path)
.output()
.expect("run");
assert!(output.status.success());
assert!(
has_bak_file(dir.path()),
"explicit --backup must create backup; ATOMWRITE_BACKUP env must be ignored"
);
}
#[test]
fn env_atomwrite_backup_nonzero_does_not_override_config_defaults_backup_false() {
let dir = tempfile::tempdir().expect("tempdir");
write_config(dir.path(), "[defaults]\nbackup = false\n");
let path = common::create_test_file(dir.path(), "f.txt", "bye\n");
let output = common::atomwrite()
.env("ATOMWRITE_BACKUP", "1")
.args([
"--workspace",
dir.path().to_str().unwrap(),
"delete",
])
.arg(&path)
.output()
.expect("run");
assert!(output.status.success());
assert!(
!has_bak_file(dir.path()),
"[defaults].backup = false must hold; ATOMWRITE_BACKUP env must be ignored"
);
}
#[test]
fn config_defaults_retention_caps_accumulated_backups() {
let dir = tempfile::tempdir().expect("tempdir");
write_config(dir.path(), "[defaults]\nbackup = true\nretention = 2\n");
for i in 0..4 {
common::create_test_file(dir.path(), "f.txt", &format!("version {i}\n"));
let output = common::atomwrite()
.env_remove("ATOMWRITE_BACKUP")
.args([
"--workspace",
dir.path().to_str().unwrap(),
"delete",
"f.txt",
])
.output()
.expect("run");
assert!(output.status.success(), "delete iteration {i} must succeed");
}
let bak_count = count_bak_files(dir.path());
assert!(
bak_count <= 2,
"[defaults].retention = 2 must limit accumulated backups to at most 2, got {bak_count}"
);
}
#[test]
fn config_present_with_retention_does_not_break_write_happy_path() {
let dir = tempfile::tempdir().expect("tempdir");
write_config(dir.path(), "[defaults]\nbackup = true\nretention = 2\n");
let output = common::atomwrite()
.env_remove("ATOMWRITE_BACKUP")
.args(["--workspace", dir.path().to_str().unwrap(), "write"])
.arg("f.txt")
.write_stdin("hello\n")
.output()
.expect("run");
assert!(
output.status.success(),
"write with .atomwrite.toml [defaults].retention present must not fail: {:?}",
String::from_utf8_lossy(&output.stderr)
);
}