use super::*;
use crate::test_support::{fixture, git_context, git_text, remove, repository};
use std::path::PathBuf;
fn blob(repo: &Path, scratch: &Path, name: &str, bytes: &[u8]) -> Option<TreeEntry> {
let file: PathBuf = scratch.join(name);
std::fs::write(&file, bytes).expect("blob file");
let oid: String = git_text(repo, &["hash-object", "-w", file.to_string_lossy().as_ref()]).trim().to_string();
return Some(TreeEntry {
mode: String::from("100644"),
oid,
});
}
fn shared(repo: &Path, scratch: &Path, sides: [Option<&[u8]>; 3]) -> SharedPath {
let entry = |index: usize, name: &str| -> Option<TreeEntry> {
return sides[index].and_then(|bytes| { return blob(repo, scratch, name, bytes); });
};
return SharedPath {
path: String::from("p.txt"),
base: entry(0, "base"),
landed: entry(1, "landed"),
prepared: entry(2, "prepared"),
};
}
fn subsumed(name: &str, base: Option<&[u8]>, landed: &[u8], prepared: &[u8]) -> bool {
let root: PathBuf = fixture(name);
let repo: PathBuf = repository(root.as_path(), "repo");
let scratch: PathBuf = root.join("scratch");
std::fs::create_dir(&scratch).expect("scratch");
let candidate: SharedPath = shared(repo.as_path(), scratch.as_path(), [base, Some(landed), Some(prepared)]);
let result: Vec<String> = subsumed_text_paths(
&git_context(),
repo.join(".git").as_path(),
repo.as_path(),
repo.join(".git").join("objects").as_path(),
&[candidate],
)
.expect("text check");
remove(root.as_path());
return !result.is_empty();
}
#[test]
fn strict_reverse_application_subsumes_the_landed_edit() {
assert!(subsumed("strict_reverse_application_subsumes_the_landed_edit", Some(b"a\nb\nc\n"), b"a\nX\nc\n", b"a\nX\nc\n"));
}
#[test]
fn an_adjacent_own_edit_is_subsumed_by_the_one_sided_extension() {
assert!(subsumed("an_adjacent_own_edit_is_subsumed_by_the_one_sided_extension", Some(b"a\nb\nc\nd\n"), b"a\nB\nc\nd\n", b"a\nB\nC\nd\n"));
}
#[test]
fn own_edits_on_both_sides_are_not_subsumed() {
assert!(!subsumed("own_edits_on_both_sides_are_not_subsumed", Some(b"a\nb\nc\nd\n"), b"a\nB\nc\nd\n", b"a\nX\nB\nC\nd\n"));
}
#[test]
fn a_prepared_file_without_the_landed_edit_is_not_subsumed() {
assert!(!subsumed("a_prepared_file_without_the_landed_edit_is_not_subsumed", Some(b"a\nb\nc\n"), b"a\nX\nc\n", b"a\nb\nc\n"));
}
#[test]
fn an_addition_on_both_sides_is_subsumed_against_the_empty_blob() {
assert!(subsumed("an_addition_on_both_sides_is_subsumed_against_the_empty_blob", None, b"a\nb\n", b"a\nX\nb\n"));
assert!(!subsumed("an_addition_on_both_sides_is_subsumed_against_the_empty_blob", None, b"a\nb\n", b"a\nX\n"));
}
#[test]
fn a_binary_blob_is_never_subsumed_by_the_text_check() {
assert!(!subsumed("a_binary_blob_is_never_subsumed_by_the_text_check", Some(b"x\0a\n"), b"x\0B\n", b"x\0B\n"));
}
#[test]
fn binary_detection_probes_the_first_bytes() {
assert!(is_binary(b"a\0"));
assert!(!is_binary(b""));
let mut late: Vec<u8> = vec![b'a'; BINARY_PROBE_BYTES];
late.push(0);
assert!(!is_binary(&late));
}
#[test]
fn no_candidates_decide_nothing() {
let root: PathBuf = fixture("replay-subsumption-empty");
let repo: PathBuf = repository(root.as_path(), "repo");
assert!(subsumed_text_paths(
&git_context(),
repo.join(".git").as_path(),
repo.as_path(),
repo.join(".git").join("objects").as_path(),
&[],
)
.expect("empty")
.is_empty());
remove(root.as_path());
}