use super::harness::{ClipSpec, clean_mirror, fast_opts, path_of, run_clean, run_sync, world};
use crate::manifest::Manifest;
use crate::reconcile::SourceStatus;
use crate::testutil::MemFs;
use crate::vocab::{AudioFormat, SourceMode};
fn assert_disk_is(fs: &MemFs, specs: &[ClipSpec]) {
let mut want: Vec<String> = specs.iter().map(path_of).collect();
want.sort();
assert_eq!(
fs.paths(),
want,
"on-disk set does not match the desired set"
);
}
#[test]
fn format_change_reformats_and_removes_the_old_file() {
let spec_mp3 = ClipSpec::mirror("c001", "Crossfade");
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(std::slice::from_ref(&spec_mp3), &fs, &mut manifest);
let old_path = path_of(&spec_mp3);
assert!(fs.exists(&old_path));
let spec_flac = spec_mp3.clone().with_format(AudioFormat::Flac);
let new_path = path_of(&spec_flac);
let (plan, outcome) = run_clean(std::slice::from_ref(&spec_flac), &fs, &mut manifest);
assert_eq!(plan.reformats(), 1);
assert_eq!(outcome.reformatted, 1);
assert!(!fs.exists(&old_path), "the old-format file must be removed");
assert!(fs.exists(&new_path), "the new-format file must be written");
assert_eq!(&fs.read_file(&new_path).unwrap()[..4], b"fLaC");
let entry = manifest.get("c001").unwrap();
assert_eq!(entry.format, AudioFormat::Flac);
assert_eq!(entry.path, new_path);
assert_eq!(fs.file_count(), 1, "no stale file is left behind");
}
#[test]
fn clip_removed_from_a_full_mirror_is_deleted() {
let specs = [
ClipSpec::mirror("c001", "Keep"),
ClipSpec::mirror("c002", "Drop"),
];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let dropped_path = path_of(&specs[1]);
assert!(fs.exists(&dropped_path));
let remaining = [specs[0].clone()];
let (plan, outcome) = run_clean(&remaining, &fs, &mut manifest);
assert_eq!(plan.deletes(), 1);
assert_eq!(outcome.deleted, 1);
assert!(!fs.exists(&dropped_path), "the orphan file must be deleted");
assert!(
manifest.get("c002").is_none(),
"the orphan entry must be dropped"
);
assert_disk_is(&fs, &remaining);
}
#[test]
fn copy_held_clip_is_never_deleted_when_it_leaves_the_mirror() {
let copy = ClipSpec::mirror("c002", "Archived").copy_held();
let specs = [ClipSpec::mirror("c001", "Plain"), copy.clone()];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let copy_path = path_of(©);
assert!(
manifest.get("c002").unwrap().preserve,
"copy hold must set preserve"
);
let mirror_only = [ClipSpec::mirror("c001", "Plain")];
let (plan, outcome) = run_clean(&mirror_only, &fs, &mut manifest);
assert_eq!(
plan.deletes(),
0,
"a preserved orphan must never be deleted"
);
assert_eq!(outcome.deleted, 0);
assert!(fs.exists(©_path), "the copy-held file survives");
assert!(
manifest.get("c002").is_some(),
"the copy-held entry survives"
);
}
#[test]
fn private_clip_is_preserved_across_removal() {
let private = ClipSpec::mirror("c002", "Secret").private();
let specs = [ClipSpec::mirror("c001", "Public"), private.clone()];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let private_path = path_of(&private);
assert!(
manifest.get("c002").unwrap().preserve,
"private must set preserve"
);
let public_only = [ClipSpec::mirror("c001", "Public")];
let (plan, outcome) = run_clean(&public_only, &fs, &mut manifest);
assert_eq!(plan.deletes(), 0);
assert_eq!(outcome.deleted, 0);
assert!(fs.exists(&private_path), "a private file is never deleted");
assert!(manifest.get("c002").is_some());
}
#[test]
fn trashed_clip_is_deleted_under_the_enumeration_guard() {
let specs = [
ClipSpec::mirror("c001", "Live"),
ClipSpec::mirror("c002", "Doomed"),
];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let doomed_path = path_of(&specs[1]);
let with_trash = [specs[0].clone(), specs[1].clone().trashed()];
let (plan, outcome) = run_clean(&with_trash, &fs, &mut manifest);
assert_eq!(plan.deletes(), 1);
assert_eq!(outcome.deleted, 1);
assert!(!fs.exists(&doomed_path));
assert!(manifest.get("c002").is_none());
}
#[test]
fn partial_listing_suppresses_every_delete() {
let specs = [ClipSpec::mirror("c001", "A"), ClipSpec::mirror("c002", "B")];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let disk_before = fs.paths();
let http = world(&[]);
let unreliable = [SourceStatus {
mode: SourceMode::Mirror,
fully_enumerated: false,
}];
let (plan, outcome) = run_sync(&[], &unreliable, &fs, &mut manifest, &http, &fast_opts());
assert_eq!(plan.deletes(), 0, "a partial listing must suppress deletes");
assert_eq!(outcome.deleted, 0);
assert_eq!(fs.paths(), disk_before, "the whole library survives");
assert_eq!(manifest.len(), 2);
}
#[test]
fn flac_first_sync_renders_transcodes_and_tags() {
let spec = ClipSpec::mirror("c001", "Lossless").with_format(AudioFormat::Flac);
let fs = MemFs::new();
let mut manifest = Manifest::new();
let (plan, outcome) = run_clean(std::slice::from_ref(&spec), &fs, &mut manifest);
assert_eq!(plan.downloads(), 1);
assert_eq!(outcome.downloaded, 1);
let path = path_of(&spec);
assert_eq!(spec.format.ext(), "flac");
assert_eq!(&fs.read_file(&path).unwrap()[..4], b"fLaC");
assert_eq!(manifest.get("c001").unwrap().format, AudioFormat::Flac);
}
#[test]
fn empty_remote_with_full_mirror_clears_a_tracked_library() {
let specs = [ClipSpec::mirror("c001", "A"), ClipSpec::mirror("c002", "B")];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let (plan, outcome) = run_sync(
&[],
&clean_mirror(),
&fs,
&mut manifest,
&world(&[]),
&fast_opts(),
);
assert_eq!(plan.deletes(), 2);
assert_eq!(outcome.deleted, 2);
assert_eq!(fs.file_count(), 0);
assert!(manifest.is_empty());
}
#[test]
fn a_preserved_copy_orphan_is_immortal_after_losing_protection_and_all_sources() {
let copy = ClipSpec::mirror("c002", "Archived").copy_held();
let specs = [ClipSpec::mirror("c001", "Plain"), copy.clone()];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let copy_path = path_of(©);
assert!(
fs.exists(©_path),
"the copy-held file lands on first sync"
);
let remaining = [ClipSpec::mirror("c001", "Plain")];
for pass in 1..=2 {
let (plan, outcome) = run_clean(&remaining, &fs, &mut manifest);
assert_eq!(
plan.deletes(),
0,
"pass {pass}: a preserved orphan must never be planned for deletion"
);
assert_eq!(outcome.deleted, 0, "pass {pass}: nothing may be deleted");
assert!(
fs.exists(©_path),
"pass {pass}: the preserved orphan file is intentionally immortal"
);
assert!(
manifest.get("c002").is_some(),
"pass {pass}: the preserved orphan manifest entry is retained forever"
);
}
}
#[test]
fn a_preserved_private_orphan_is_immortal_after_losing_protection_and_all_sources() {
let private = ClipSpec::mirror("c002", "Secret").private();
let specs = [ClipSpec::mirror("c001", "Public"), private.clone()];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let private_path = path_of(&private);
assert!(
fs.exists(&private_path),
"the private file lands on first sync"
);
let remaining = [ClipSpec::mirror("c001", "Public")];
for pass in 1..=2 {
let (plan, outcome) = run_clean(&remaining, &fs, &mut manifest);
assert_eq!(
plan.deletes(),
0,
"pass {pass}: a preserved private orphan is never planned for deletion"
);
assert_eq!(outcome.deleted, 0, "pass {pass}: nothing may be deleted");
assert!(
fs.exists(&private_path),
"pass {pass}: the preserved private orphan is intentionally immortal"
);
assert!(
manifest.get("c002").is_some(),
"pass {pass}: the preserved private orphan entry is retained forever"
);
}
}
#[test]
fn partial_copy_source_suppresses_delete_end_to_end() {
let specs = [
ClipSpec::mirror("c001", "Keep"),
ClipSpec::mirror("c002", "Maybe"),
];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let maybe_path = path_of(&specs[1]);
let remaining = [ClipSpec::mirror("c001", "Keep")];
let sources = [
SourceStatus {
mode: SourceMode::Mirror,
fully_enumerated: true,
},
SourceStatus {
mode: SourceMode::Copy,
fully_enumerated: false,
},
];
let http = world(&remaining);
let (plan, outcome) = run_sync(
&remaining,
&sources,
&fs,
&mut manifest,
&http,
&fast_opts(),
);
assert_eq!(
plan.deletes(),
0,
"an unreliable copy source must suppress every delete"
);
assert_eq!(outcome.deleted, 0);
assert!(
fs.exists(&maybe_path),
"the orphan survives the unreliable copy run"
);
assert!(manifest.get("c002").is_some());
}
#[test]
fn copy_held_trashed_clip_survives_end_to_end() {
let keep = ClipSpec::mirror("c002", "Trashed but archived").copy_held();
let specs = [ClipSpec::mirror("c001", "Doomed"), keep.clone()];
let fs = MemFs::new();
let mut manifest = Manifest::new();
run_clean(&specs, &fs, &mut manifest);
let keep_path = path_of(&keep);
let doomed_path = path_of(&specs[0]);
let trashed = [
ClipSpec::mirror("c001", "Doomed").trashed(),
keep.clone().trashed(),
];
let (plan, outcome) = run_clean(&trashed, &fs, &mut manifest);
assert_eq!(
plan.deletes(),
1,
"only the unprotected trashed clip is deleted"
);
assert_eq!(outcome.deleted, 1);
assert!(
!fs.exists(&doomed_path),
"the mirror-only trashed clip is deleted"
);
assert!(
fs.exists(&keep_path),
"the copy-held trashed clip is kept end to end"
);
assert!(
manifest.get("c002").is_some(),
"the copy-held trashed clip's manifest entry is retained"
);
}