use super::*;
use base64::Engine;
const JAR_BYTES: &[u8] = &[0x50, 0x4b, 0x03, 0x04, 0x00, 0xff, 0xfe, 0x01];
fn encoded_jar() -> String {
base64::engine::general_purpose::STANDARD.encode(JAR_BYTES)
}
fn seed_bytes(base: &Path, relative: &str, bytes: &[u8]) -> PathBuf {
let full = base.join(relative);
std::fs::create_dir_all(full.parent().expect("parent")).expect("mkdir");
std::fs::write(&full, bytes).expect("seed bytes");
full
}
#[test]
fn a_binary_match_does_not_stop_the_text_matches_beside_it_from_being_adopted() {
let base = tempfile::tempdir().expect("tempdir");
let root = base.path();
let mut outputs = managed("packages/demo/config.toml", "name = \"demo\"\n", true, root);
outputs.extend(managed("packages/demo/wrapper.jar", &encoded_jar(), false, root));
seed(root, "packages/demo/config.toml", "name = \"demo\"\n");
let binary = seed_bytes(root, "packages/demo/wrapper.jar", &[0xff, 0xfe, 0x00, 0x01]);
let report = run(&clobbering_seeds(root, "packages/**"), &outputs).expect("adopt must not abort on a binary match");
assert!(report.unreadable.is_empty(), "a decodable jar is not unreadable");
assert_eq!(
std::fs::read(&binary).expect("binary still readable"),
vec![0xff, 0xfe, 0x00, 0x01],
"adoption never rewrites content -- the binary's bytes must be untouched"
);
assert!(
content_has_alef_marker(&std::fs::read_to_string(root.join("packages/demo/config.toml")).expect("read")),
"the text file under the same glob must still have been adopted"
);
}
#[test]
fn a_drifted_binary_is_adopted_through_the_durable_ownership_record() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let relative = "packages/kotlin-android/gradle/wrapper/gradle-wrapper.jar";
let on_disk = [0xff, 0xfe, 0x00, 0x01];
let target = seed_bytes(base, relative, &on_disk);
assert!(!crate::cli::cache::is_scaffold_owned_path(base, &target));
let outputs = managed(relative, &encoded_jar(), false, base);
let report = run(&clobbering_seeds(base, relative), &outputs).expect("adopt");
assert_eq!(
std::fs::read(&target).expect("read after"),
on_disk,
"a binary's bytes must not change: the record carries the ownership proof"
);
assert!(
crate::cli::cache::is_scaffold_owned_path(base, &target),
"the guard's own ownership question must now answer yes"
);
assert_eq!(report.recorded_unstampable, vec![PathBuf::from(relative)]);
assert_eq!(report.adopted, vec![PathBuf::from(relative)]);
std::fs::remove_dir_all(base.join(".alef")).ok();
assert!(base.join(".alef-ownership.toml").exists());
assert!(crate::cli::cache::is_scaffold_owned_path(base, &target));
}
#[test]
fn a_drifted_binary_reports_both_sides_by_size_and_digest_before_adoption() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let relative = "packages/demo/wrapper.jar";
seed_bytes(base, relative, &[0xff, 0xfe, 0x00, 0x01]);
let outputs = managed(relative, &encoded_jar(), false, base);
let report = run(&previewing_seeds(base, relative), &outputs).expect("adopt preview");
let diff = report
.diffs
.first()
.expect("a drifted binary must produce a reviewable diff");
assert_eq!(diff.state, AdoptionState::Drifted);
assert!(
diff.body.contains("4 bytes") && diff.body.contains("8 bytes"),
"both sides' sizes must be stated, got:\n{}",
diff.body
);
assert!(
diff.body
.contains(&crate::core::hash::hash_bytes(&[0xff, 0xfe, 0x00, 0x01]))
&& diff.body.contains(&crate::core::hash::hash_bytes(JAR_BYTES)),
"both sides' digests must be stated, got:\n{}",
diff.body
);
assert!(report.adopted.is_empty(), "a preview writes nothing");
}
#[test]
fn a_binary_matching_its_generated_bytes_is_converged_not_drifted() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let relative = "packages/demo/wrapper.jar";
seed_bytes(base, relative, JAR_BYTES);
let outputs = managed(relative, &encoded_jar(), false, base);
let report = run(&previewing_seeds(base, relative), &outputs).expect("adopt preview");
assert_eq!(report.converged, vec![PathBuf::from(relative)]);
assert!(report.diffs.is_empty());
}
#[test]
fn a_binary_seed_is_refused_by_default_with_the_flag_that_adopts_it_named() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let relative = "packages/demo/wrapper.jar";
seed_bytes(base, relative, &[0xff, 0xfe, 0x00, 0x01]);
let outputs = managed(relative, &encoded_jar(), false, base);
let error = run(&options(base, relative, true), &outputs).expect_err("a bare --write must refuse a seed");
assert!(
format!("{error:#}").contains("--clobber-create-once-seeds"),
"the refusal must name the flag that resolves it, got: {error:#}"
);
}
#[test]
fn a_non_binary_output_with_invalid_utf8_bytes_is_still_refused() {
let dir = tempfile::tempdir().expect("tempdir");
let base = dir.path();
let relative = "packages/demo/config.toml";
let target = seed_bytes(base, relative, &[0xff, 0xfe, 0x00, 0x01]);
let outputs = managed(relative, "name = \"demo\"\n", true, base);
let report = run(&options(base, relative, true), &outputs).expect("adopt");
assert_eq!(report.unreadable, vec![PathBuf::from(relative)]);
assert!(report.adopted.is_empty());
assert!(!crate::cli::cache::is_scaffold_owned_path(base, &target));
}