use super::*;
fn base() -> Vec<Vec<u8>> {
return ["a\n", "b\n", "c\n", "d\n", "e\n"]
.iter()
.map(|line| { return line.as_bytes().to_vec(); })
.collect();
}
fn hunk(old_start: i64, new_start: i64, lines: &[(u8, &str)]) -> PatchHunk {
return PatchHunk {
old_start,
new_start,
lines: lines
.iter()
.map(|(op, text)| { return PatchLine {
op: *op,
text: text.as_bytes().to_vec(),
}; })
.collect(),
};
}
fn landed_b() -> Vec<PatchHunk> {
return vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "B\n")])];
}
#[test]
fn an_exact_match_is_contained() {
let prepared: Vec<PatchHunk> = landed_b();
assert!(contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn an_own_line_after_the_landed_line_is_contained() {
let prepared: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "B\n"), (b'+', "X\n")])];
assert!(contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn an_own_line_before_the_landed_line_is_contained() {
let prepared: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "X\n"), (b'+', "B\n")])];
assert!(contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn own_lines_on_both_sides_are_not_contained() {
let prepared: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "X\n"), (b'+', "B\n"), (b'+', "Y\n")])];
assert!(!contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn a_far_apart_prepared_change_does_not_contain_the_landed_change() {
let prepared: Vec<PatchHunk> = vec![hunk(4, 4, &[(b'-', "d\n"), (b'+', "D\n")])];
assert!(!contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn a_prepared_rewrite_of_a_landed_line_is_not_contained() {
let prepared: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "Z\n")])];
assert!(!contains_landed_change(&landed_b(), &prepared, &base()));
}
#[test]
fn a_prefix_extension_is_contained() {
let landed: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'-', "c\n"), (b'+', "B\n"), (b'+', "C\n")])];
let prepared: Vec<PatchHunk> = vec![hunk(
2,
2,
&[(b'-', "b\n"), (b'-', "c\n"), (b'-', "d\n"), (b'+', "B\n"), (b'+', "C\n"), (b'+', "X\n")],
)];
assert!(contains_landed_change(&landed, &prepared, &base()));
}
#[test]
fn a_suffix_extension_is_contained() {
let landed: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'-', "c\n"), (b'+', "B\n"), (b'+', "C\n")])];
let prepared: Vec<PatchHunk> = vec![hunk(
1,
1,
&[(b'-', "a\n"), (b'-', "b\n"), (b'-', "c\n"), (b'+', "X\n"), (b'+', "B\n"), (b'+', "C\n")],
)];
assert!(contains_landed_change(&landed, &prepared, &base()));
}
#[test]
fn two_landed_hunks_inside_one_prepared_hunk_are_contained() {
let landed: Vec<PatchHunk> = vec![
hunk(2, 2, &[(b'-', "b\n"), (b'+', "B\n")]),
hunk(4, 4, &[(b'-', "d\n"), (b'+', "D\n")]),
];
let prepared: Vec<PatchHunk> = vec![hunk(
2,
2,
&[(b'-', "b\n"), (b'-', "c\n"), (b'-', "d\n"), (b'+', "B\n"), (b'+', "c\n"), (b'+', "D\n")],
)];
assert!(contains_landed_change(&landed, &prepared, &base()));
let dropped: Vec<PatchHunk> = vec![hunk(
2,
2,
&[(b'-', "b\n"), (b'-', "c\n"), (b'-', "d\n"), (b'+', "B\n"), (b'+', "D\n")],
)];
assert!(!contains_landed_change(&landed, &dropped, &base()));
}
#[test]
fn deletions_are_contained_only_when_both_sides_delete() {
let landed: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n")])];
let deleted: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n")])];
let rewritten: Vec<PatchHunk> = vec![hunk(2, 2, &[(b'-', "b\n"), (b'+', "X\n")])];
assert!(contains_landed_change(&landed, &deleted, &base()));
assert!(!contains_landed_change(&landed, &rewritten, &base()));
}
#[test]
fn additions_against_an_empty_base_keep_every_landed_line() {
let empty: Vec<Vec<u8>> = Vec::new();
let landed: Vec<PatchHunk> = vec![hunk(0, 1, &[(b'+', "a\n"), (b'+', "b\n")])];
let kept: Vec<PatchHunk> = vec![hunk(0, 1, &[(b'+', "a\n"), (b'+', "X\n"), (b'+', "b\n")])];
let before: Vec<PatchHunk> = vec![hunk(0, 1, &[(b'+', "X\n"), (b'+', "a\n"), (b'+', "b\n")])];
let dropped: Vec<PatchHunk> = vec![hunk(0, 1, &[(b'+', "a\n"), (b'+', "X\n")])];
assert!(contains_landed_change(&landed, &kept, &empty));
assert!(contains_landed_change(&landed, &before, &empty));
assert!(!contains_landed_change(&landed, &dropped, &empty));
}
#[test]
fn a_landed_insertion_is_contained_by_a_prepared_hunk_ending_at_it() {
let landed: Vec<PatchHunk> = vec![hunk(1, 1, &[(b'+', "X\n")])];
let prepared: Vec<PatchHunk> = vec![hunk(1, 1, &[(b'-', "a\n"), (b'+', "a\n"), (b'+', "X\n")])];
assert!(contains_landed_change(&landed, &prepared, &base()));
}
#[test]
fn no_landed_change_is_contained() {
assert!(contains_landed_change(&[], &landed_b(), &base()));
assert!(!contains_landed_change(&landed_b(), &[], &base()));
}