use assert_cmd::assert::Assert;
mod common;
use common::{run, run_ok};
#[test]
fn non_utf8_content_round_trips() {
let mut input = Vec::new();
input.extend_from_slice(b"--- a/f\n+++ b/f\n@@ -1 +1 @@\n-caf");
input.push(0xE9);
input.push(b'\n');
input.extend_from_slice(b"+CAF");
input.push(0xE9);
input.push(b'\n');
let out = run_ok(&["select", "1"], input);
assert_eq!(
out.iter().filter(|&&b| b == 0xE9).count(),
2,
"both 0xE9 bytes must be preserved in output: {out:?}"
);
}
fn the_diagnosis_for(stream: impl AsRef<[u8]>) -> Assert {
run(&["list"], stream).failure().code(2)
}
#[test]
fn nul_byte_input_exits_2() {
the_diagnosis_for(vec![0u8, 1, 2, b'h', b'i']).stderr(predicates::str::contains("NUL byte"));
}
#[test]
fn non_diff_text_exits_2() {
the_diagnosis_for("hello world\nthis is not a diff\n")
.stderr(predicates::str::contains("no diff markers found"));
}
#[test]
fn empty_input_list_is_noop() {
run(&["list"], "").success().stdout(predicates::ord::eq(""));
}
#[test]
fn empty_input_select_is_noop() {
run(&["select", "1"], "")
.success()
.stdout(predicates::ord::eq(""));
}
#[test]
fn whitespace_only_input_is_noop() {
run(&["select", "1"], " \n\t\n")
.success()
.stdout(predicates::ord::eq(""));
}
#[test]
fn a_non_ascii_space_in_the_hunk_header_exits_2() {
let input = "diff --git a/f b/f\n--- a/f\n+++ b/f\n@@ -1,3\u{a0}+1,3 @@\n a\n-b\n+B\n c\n";
run(&["select", "*"], input)
.failure()
.code(2)
.stderr(predicates::str::contains("malformed hunk header"));
}
fn a_utf16_diff(ending: &str, to_bytes: fn(u16) -> [u8; 2]) -> Vec<u8> {
let text = format!(
"diff --git a/f b/f{ending}--- a/f{ending}+++ b/f{ending}\
@@ -1 +1 @@{ending}-old{ending}+new{ending}"
);
text.encode_utf16().flat_map(to_bytes).collect()
}
#[test]
fn a_utf16_diff_without_a_bom_names_the_encoding() {
the_diagnosis_for(a_utf16_diff("\n", u16::to_le_bytes))
.stderr(predicates::str::contains("UTF-16LE"));
}
#[test]
fn a_utf16be_diff_without_a_bom_names_the_encoding() {
the_diagnosis_for(a_utf16_diff("\n", u16::to_be_bytes))
.stderr(predicates::str::contains("UTF-16BE"));
}
#[test]
fn a_utf16_diff_written_with_carriage_returns_names_the_encoding() {
the_diagnosis_for(a_utf16_diff("\r\n", u16::to_le_bytes))
.stderr(predicates::str::contains("UTF-16LE"));
}
#[test]
fn binary_input_is_still_reported_as_binary() {
the_diagnosis_for(vec![
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D,
])
.stderr(predicates::str::contains("binary input"));
}
#[test]
fn a_quoted_path_round_trips_and_is_addressable_by_its_bytes() {
let input = concat!(
"diff --git \"a/\\303\\251.txt\" \"b/\\303\\251.txt\"\n",
"--- \"a/\\303\\251.txt\"\n",
"+++ \"b/\\303\\251.txt\"\n",
"@@ -1,3 +1,3 @@\n one\n-two\n+TWO\n three\n",
);
let out = run_ok(&["select", "\u{e9}.txt:1"], input);
assert_eq!(String::from_utf8_lossy(&out), input);
}