use super::*; #[test] fn sync_mode_selects_snapshot_delta_and_recovery() { let root = tempfile::tempdir().unwrap(); assert_eq!(sync_mode(root.path(), false).unwrap(), "snapshot"); let db = root.path().join("repository-db"); fs::create_dir(&db).unwrap(); assert_eq!(sync_mode(root.path(), true).unwrap(), "snapshot"); fs::write(db.join("CURRENT"), b"x").unwrap(); assert_eq!(sync_mode(root.path(), true).unwrap(), "delta"); assert_eq!(sync_mode(root.path(), false).unwrap(), "auto"); } #[test] fn retention_keeps_incomplete_and_latest_runs() { let root = tempfile::tempdir().unwrap(); let runs = root.path().join("runs"); fs::create_dir(&runs).unwrap(); for (seq, result_status) in [(1, "success"), (2, "partial"), (3, "failed")] { let path = runs.join(format!("run_{seq:06}")); fs::create_dir(&path).unwrap(); write_json_pretty( &path.join("run-summary.json"), &json!({ "controller": "panda-rpki-daemon-v1", "run_seq": seq, "status": if result_status == "success" { "success" } else { "failed" }, "resultStatus": result_status, }), ) .unwrap(); } std::os::unix::fs::symlink("runs/run_000001", root.path().join("latest")).unwrap(); // Only completed runs are candidates; partial is completed evidence and is retained // alongside the latest pointer even when the retention limit is one. assert_eq!(apply_retention(&runs, 1).unwrap(), ["run_000002"]); assert!(runs.join("run_000001").exists()); assert!(!runs.join("run_000002").exists()); assert!(runs.join("run_000003").exists()); } #[test] fn retention_ignores_unrelated_paths_and_symlinks() { let root = tempfile::tempdir().unwrap(); let runs = root.path().join("runs"); fs::create_dir(&runs).unwrap(); let path = runs.join("run_000001"); fs::create_dir(&path).unwrap(); write_json_pretty( &path.join("run-summary.json"), &json!({"controller": "other", "run_seq": 1, "status": "success"}), ) .unwrap(); fs::create_dir(runs.join("unrelated")).unwrap(); let outside = tempfile::tempdir().unwrap(); std::os::unix::fs::symlink(outside.path(), runs.join("run_000002")).unwrap(); assert!(apply_retention(&runs, 0).unwrap().is_empty()); assert!(runs.join("run_000001").exists()); assert!(runs.join("run_000002").exists()); assert!(runs.join("unrelated").exists()); } #[test] fn atomic_json_writer_replaces_content() { let root = tempfile::tempdir().unwrap(); let path = root.path().join("state.json"); write_json_pretty(&path, &json!({"seq": 1})).unwrap(); write_json_pretty(&path, &json!({"seq": 2})).unwrap(); assert_eq!(read_json(&path).unwrap()["seq"], 2); }