fix(sync): S-09 — pull overwrite protection and conflict safety
This commit is contained in:
@@ -1064,3 +1064,128 @@ fn test_s08_refined_glob_and_directory_exclusions() {
|
||||
let _ = fs::remove_dir_all(&temp_root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_s09_pull_backup_and_update_conflict_safety() {
|
||||
let temp_root =
|
||||
std::env::temp_dir().join(format!("sanctum_s09_test_{}", rand::random::<u64>()));
|
||||
let container_path = temp_root.join("s09.sanctum");
|
||||
let source_dir = temp_root.join("source");
|
||||
let local_dest_dir = temp_root.join("dest");
|
||||
|
||||
fs::create_dir_all(&source_dir).unwrap();
|
||||
fs::create_dir_all(&local_dest_dir).unwrap();
|
||||
|
||||
let (db, dek) = create_test_container(&container_path);
|
||||
|
||||
// Datei in den Tresor laden
|
||||
fs::write(source_dir.join("document.txt"), b"Vault Version 2.0").unwrap();
|
||||
fs::write(source_dir.join("notes.txt"), b"Older Vault Notes").unwrap();
|
||||
|
||||
let mut push_opts = SyncOptions::default();
|
||||
push_opts.direction = SyncDirection::Push;
|
||||
push_opts.quiet = true;
|
||||
run_sync(
|
||||
&db,
|
||||
0,
|
||||
&dek,
|
||||
FORMAT_VERSION,
|
||||
source_dir.to_str().unwrap(),
|
||||
"/",
|
||||
&push_opts,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// 1. Test Backup-Erstellung (--backup):
|
||||
// Lokale Datei anlegen mit eigenem Inhalt
|
||||
let local_doc = local_dest_dir.join("document.txt");
|
||||
fs::write(&local_doc, b"Local Version 1.0 (Must be backed up)").unwrap();
|
||||
|
||||
let mut pull_opts = SyncOptions::default();
|
||||
pull_opts.direction = SyncDirection::Pull;
|
||||
pull_opts.quiet = true;
|
||||
pull_opts.backup = true;
|
||||
|
||||
let pull_stats = run_sync(
|
||||
&db,
|
||||
0,
|
||||
&dek,
|
||||
FORMAT_VERSION,
|
||||
"/",
|
||||
local_dest_dir.to_str().unwrap(),
|
||||
&pull_opts,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(pull_stats.files_backed_up, 1);
|
||||
assert_eq!(fs::read(&local_doc).unwrap(), b"Vault Version 2.0");
|
||||
|
||||
let backup_doc = local_dest_dir.join("document.txt.bak");
|
||||
assert!(
|
||||
backup_doc.exists(),
|
||||
"Backup-Datei .bak muss angelegt worden sein"
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read(&backup_doc).unwrap(),
|
||||
b"Local Version 1.0 (Must be backed up)"
|
||||
);
|
||||
|
||||
// 2. Test Konfliktschutz (--update):
|
||||
// Erzeuge lokale notes.txt mit neuerem Timestamp
|
||||
let local_notes = local_dest_dir.join("notes.txt");
|
||||
fs::write(&local_notes, b"Newer Local Notes").unwrap();
|
||||
let future_time = std::time::UNIX_EPOCH + std::time::Duration::from_secs(2_000_000_000);
|
||||
fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.open(&local_notes)
|
||||
.unwrap()
|
||||
.set_times(std::fs::FileTimes::new().set_modified(future_time))
|
||||
.expect("Set modified time on local_notes");
|
||||
|
||||
let mut update_opts = SyncOptions::default();
|
||||
update_opts.direction = SyncDirection::Pull;
|
||||
update_opts.quiet = true;
|
||||
update_opts.update = true;
|
||||
|
||||
let update_stats = run_sync(
|
||||
&db,
|
||||
0,
|
||||
&dek,
|
||||
FORMAT_VERSION,
|
||||
"/",
|
||||
local_dest_dir.to_str().unwrap(),
|
||||
&update_opts,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// notes.txt darf NICHT überschrieben worden sein
|
||||
assert_eq!(
|
||||
fs::read(&local_notes).unwrap(),
|
||||
b"Newer Local Notes",
|
||||
"Neuere lokale Datei darf mit --update nicht überschrieben werden"
|
||||
);
|
||||
assert!(update_stats.files_skipped >= 1);
|
||||
|
||||
// Mit --force muss sie überschrieben werden
|
||||
update_opts.force = true;
|
||||
let force_stats = run_sync(
|
||||
&db,
|
||||
0,
|
||||
&dek,
|
||||
FORMAT_VERSION,
|
||||
"/",
|
||||
local_dest_dir.to_str().unwrap(),
|
||||
&update_opts,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
fs::read(&local_notes).unwrap(),
|
||||
b"Older Vault Notes",
|
||||
"Mit --force muss die neuere Datei dennoch überschrieben werden"
|
||||
);
|
||||
assert_eq!(force_stats.files_transferred, 1);
|
||||
|
||||
let _ = fs::remove_dir_all(&temp_root);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user