Skip to content

Commit a046e26

Browse files
authored
Merge pull request #2288 from cruessler/update-imara-diff
Update to `imara-diff` 0.2 in diff slider test
2 parents 2b3037e + 5130610 commit a046e26

File tree

1 file changed

+140
-41
lines changed

1 file changed

+140
-41
lines changed

gix-diff/tests/diff/blob/slider.rs

Lines changed: 140 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use gix_diff::blob::intern::TokenSource;
2-
use gix_diff::blob::unified_diff::ContextSize;
3-
use gix_diff::blob::{Algorithm, UnifiedDiff};
1+
use gix_object::bstr::ByteSlice;
42
use gix_testtools::bstr::{BString, ByteVec};
53
use pretty_assertions::StrComparison;
64

75
#[test]
8-
fn baseline() -> gix_testtools::Result {
6+
fn baseline_v1() -> gix_testtools::Result {
7+
use gix_diff::blob::{unified_diff::ContextSize, UnifiedDiff};
8+
99
let worktree_path = gix_testtools::scripted_fixture_read_only_standalone("make_diff_for_sliders_repo.sh")?;
1010
let asset_dir = worktree_path.join("assets");
1111

@@ -15,30 +15,16 @@ fn baseline() -> gix_testtools::Result {
1515

1616
for entry in dir {
1717
let entry = entry?;
18-
let file_name = entry.file_name().into_string().expect("to be string");
19-
20-
if !file_name.ends_with(".baseline") {
18+
let Some(baseline::DirEntry {
19+
file_name,
20+
algorithm,
21+
old_data,
22+
new_data,
23+
}) = baseline::parse_dir_entry(&asset_dir, &entry.file_name())?
24+
else {
2125
continue;
22-
}
23-
24-
let parts: Vec<_> = file_name.split('.').collect();
25-
let [name, algorithm, ..] = parts[..] else {
26-
unreachable!()
27-
};
28-
let algorithm = match algorithm {
29-
"myers" => Algorithm::Myers,
30-
"histogram" => Algorithm::Histogram,
31-
_ => unreachable!(),
32-
};
33-
34-
let parts: Vec<_> = name.split('-').collect();
35-
let [old_blob_id, new_blob_id] = parts[..] else {
36-
unreachable!();
3726
};
3827

39-
let old_data = std::fs::read(asset_dir.join(format!("{old_blob_id}.blob")))?;
40-
let new_data = std::fs::read(asset_dir.join(format!("{new_blob_id}.blob")))?;
41-
4228
let interner = gix_diff::blob::intern::InternedInput::new(
4329
tokens_for_diffing(old_data.as_slice()),
4430
tokens_for_diffing(new_data.as_slice()),
@@ -70,17 +56,74 @@ fn baseline() -> gix_testtools::Result {
7056
})
7157
.to_string();
7258

73-
let baseline = baseline
74-
.fold(BString::default(), |mut acc, diff_hunk| {
75-
acc.push_str(diff_hunk.header.to_string().as_str());
76-
acc.push(b'\n');
59+
let baseline = baseline.fold_to_unidiff().to_string();
60+
let actual_matches_baseline = actual == baseline;
61+
diffs.push((actual, baseline, actual_matches_baseline, file_name));
62+
}
7763

78-
acc.extend_from_slice(&diff_hunk.lines);
64+
if diffs.is_empty() {
65+
eprintln!("Slider baseline isn't setup - look at ./gix-diff/tests/README.md for instructions");
66+
}
7967

80-
acc
81-
})
68+
assert_diffs(&diffs);
69+
70+
Ok(())
71+
}
72+
73+
fn tokens_for_diffing(data: &[u8]) -> impl gix_diff::blob::intern::TokenSource<Token = &[u8]> {
74+
gix_diff::blob::sources::byte_lines(data)
75+
}
76+
77+
#[test]
78+
fn baseline_v2() -> gix_testtools::Result {
79+
use gix_diff::blob::v2::{Algorithm, BasicLineDiffPrinter, Diff, InternedInput, UnifiedDiffConfig};
80+
81+
let worktree_path = gix_testtools::scripted_fixture_read_only_standalone("make_diff_for_sliders_repo.sh")?;
82+
let asset_dir = worktree_path.join("assets");
83+
84+
let dir = std::fs::read_dir(&worktree_path)?;
85+
86+
let mut diffs = Vec::new();
87+
88+
for entry in dir {
89+
let entry = entry?;
90+
let Some(baseline::DirEntry {
91+
file_name,
92+
algorithm,
93+
old_data,
94+
new_data,
95+
}) = baseline::parse_dir_entry(&asset_dir, &entry.file_name())?
96+
else {
97+
continue;
98+
};
99+
100+
let input = InternedInput::new(
101+
old_data.to_str().expect("BUG: we don't have non-ascii here"),
102+
new_data.to_str().expect("BUG: we don't have non-ascii here"),
103+
);
104+
let algorithm = match algorithm {
105+
gix_diff::blob::Algorithm::Myers => Algorithm::Myers,
106+
gix_diff::blob::Algorithm::Histogram => Algorithm::Histogram,
107+
gix_diff::blob::Algorithm::MyersMinimal => Algorithm::MyersMinimal,
108+
};
109+
110+
let mut diff = Diff::compute(algorithm, &input);
111+
diff.postprocess_lines(&input);
112+
113+
let actual = diff
114+
.unified_diff(
115+
&BasicLineDiffPrinter(&input.interner),
116+
UnifiedDiffConfig::default(),
117+
&input,
118+
)
82119
.to_string();
83120

121+
let baseline_path = worktree_path.join(&file_name);
122+
let baseline = std::fs::read(baseline_path)?;
123+
let baseline = baseline::Baseline::new(&baseline);
124+
125+
let baseline = baseline.fold_to_unidiff().to_string();
126+
84127
let actual_matches_baseline = actual == baseline;
85128
diffs.push((actual, baseline, actual_matches_baseline, file_name));
86129
}
@@ -89,6 +132,11 @@ fn baseline() -> gix_testtools::Result {
89132
eprintln!("Slider baseline isn't setup - look at ./gix-diff/tests/README.md for instructions");
90133
}
91134

135+
assert_diffs(&diffs);
136+
Ok(())
137+
}
138+
139+
fn assert_diffs(diffs: &[(String, String, bool, String)]) {
92140
let total_diffs = diffs.len();
93141
let matching_diffs = diffs
94142
.iter()
@@ -115,20 +163,16 @@ fn baseline() -> gix_testtools::Result {
115163
)
116164
}
117165
);
118-
119-
Ok(())
120-
}
121-
122-
fn tokens_for_diffing(data: &[u8]) -> impl TokenSource<Token = &[u8]> {
123-
gix_diff::blob::sources::byte_lines(data)
124166
}
125167

126168
mod baseline {
127-
use gix_object::bstr::ByteSlice;
128-
use std::iter::Peekable;
129-
130169
use gix_diff::blob::unified_diff::{ConsumeHunk, HunkHeader};
170+
use gix_diff::blob::Algorithm;
131171
use gix_object::bstr::{self, BString};
172+
use gix_object::bstr::{ByteSlice, ByteVec};
173+
use std::ffi::OsStr;
174+
use std::iter::Peekable;
175+
use std::path::Path;
132176

133177
static START_OF_HEADER: &[u8; 4] = b"@@ -";
134178

@@ -193,6 +237,20 @@ mod baseline {
193237
}
194238
}
195239

240+
impl Baseline<'_> {
241+
/// Converts all baseline [`DiffHunk`]s into a single unified diff format string.
242+
pub fn fold_to_unidiff(self) -> BString {
243+
self.fold(BString::default(), |mut acc, diff_hunk| {
244+
acc.push_str(diff_hunk.header.to_string().as_str());
245+
acc.push(b'\n');
246+
247+
acc.extend_from_slice(&diff_hunk.lines);
248+
249+
acc
250+
})
251+
}
252+
}
253+
196254
impl Iterator for Baseline<'_> {
197255
type Item = DiffHunk;
198256

@@ -285,4 +343,45 @@ mod baseline {
285343
.parse::<u32>()
286344
.expect("to be a number")
287345
}
346+
347+
pub struct DirEntry {
348+
pub file_name: String,
349+
pub algorithm: Algorithm,
350+
pub old_data: Vec<u8>,
351+
pub new_data: Vec<u8>,
352+
}
353+
354+
/// Returns `None` if the file isn't a baseline entry.
355+
pub fn parse_dir_entry(asset_dir: &Path, file_name: &OsStr) -> std::io::Result<Option<DirEntry>> {
356+
let file_name = file_name.to_str().expect("ascii filename").to_owned();
357+
358+
if !file_name.ends_with(".baseline") {
359+
return Ok(None);
360+
}
361+
362+
let parts: Vec<_> = file_name.split('.').collect();
363+
let [name, algorithm, ..] = parts[..] else {
364+
unreachable!("BUG: Need file named '<name>.<algorithm>'")
365+
};
366+
let algorithm = match algorithm {
367+
"myers" => Algorithm::Myers,
368+
"histogram" => Algorithm::Histogram,
369+
other => unreachable!("BUG: '{other}' is not a supported algorithm"),
370+
};
371+
372+
let parts: Vec<_> = name.split('-').collect();
373+
let [old_blob_id, new_blob_id] = parts[..] else {
374+
unreachable!("BUG: name part of filename must be '<old_blob_id>-<new_blob_id>'");
375+
};
376+
377+
let old_data = std::fs::read(asset_dir.join(format!("{old_blob_id}.blob")))?;
378+
let new_data = std::fs::read(asset_dir.join(format!("{new_blob_id}.blob")))?;
379+
Ok(DirEntry {
380+
file_name,
381+
algorithm,
382+
old_data,
383+
new_data,
384+
}
385+
.into())
386+
}
288387
}

0 commit comments

Comments
 (0)