1- use gix_diff:: blob:: v2:: { Algorithm , BasicLineDiffPrinter , Diff , InternedInput , UnifiedDiffConfig } ;
21use gix_object:: bstr:: ByteSlice ;
32use gix_testtools:: bstr:: { BString , ByteVec } ;
43use pretty_assertions:: StrComparison ;
54
65#[ test]
7- fn baseline ( ) -> gix_testtools:: Result {
6+ fn baseline_v1 ( ) -> gix_testtools:: Result {
7+ use gix_diff:: blob:: { unified_diff:: ContextSize , Algorithm , UnifiedDiff } ;
8+
9+ let worktree_path = gix_testtools:: scripted_fixture_read_only_standalone ( "make_diff_for_sliders_repo.sh" ) ?;
10+ let asset_dir = worktree_path. join ( "assets" ) ;
11+
12+ let dir = std:: fs:: read_dir ( & worktree_path) ?;
13+
14+ let mut diffs = Vec :: new ( ) ;
15+
16+ for entry in dir {
17+ let entry = entry?;
18+ let file_name = entry. file_name ( ) . into_string ( ) . expect ( "to be string" ) ;
19+
20+ if !file_name. ends_with ( ".baseline" ) {
21+ 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 ! ( ) ;
37+ } ;
38+
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+
42+ let interner = gix_diff:: blob:: intern:: InternedInput :: new (
43+ tokens_for_diffing ( old_data. as_slice ( ) ) ,
44+ tokens_for_diffing ( new_data. as_slice ( ) ) ,
45+ ) ;
46+
47+ let actual = gix_diff:: blob:: diff (
48+ algorithm,
49+ & interner,
50+ UnifiedDiff :: new (
51+ & interner,
52+ baseline:: DiffHunkRecorder :: new ( ) ,
53+ ContextSize :: symmetrical ( 3 ) ,
54+ ) ,
55+ ) ?;
56+
57+ let baseline_path = worktree_path. join ( & file_name) ;
58+ let baseline = std:: fs:: read ( baseline_path) ?;
59+ let baseline = baseline:: Baseline :: new ( & baseline) ;
60+
61+ let actual = actual
62+ . iter ( )
63+ . fold ( BString :: default ( ) , |mut acc, diff_hunk| {
64+ acc. push_str ( diff_hunk. header . to_string ( ) . as_str ( ) ) ;
65+ acc. push ( b'\n' ) ;
66+
67+ acc. extend_from_slice ( & diff_hunk. lines ) ;
68+
69+ acc
70+ } )
71+ . to_string ( ) ;
72+
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' ) ;
77+
78+ acc. extend_from_slice ( & diff_hunk. lines ) ;
79+
80+ acc
81+ } )
82+ . to_string ( ) ;
83+
84+ let actual_matches_baseline = actual == baseline;
85+ diffs. push ( ( actual, baseline, actual_matches_baseline, file_name) ) ;
86+ }
87+
88+ if diffs. is_empty ( ) {
89+ eprintln ! ( "Slider baseline isn't setup - look at ./gix-diff/tests/README.md for instructions" ) ;
90+ }
91+
92+ let total_diffs = diffs. len ( ) ;
93+ let matching_diffs = diffs
94+ . iter ( )
95+ . filter ( |( _, _, actual_matches_baseline, _) | * actual_matches_baseline)
96+ . count ( ) ;
97+
98+ assert_eq ! (
99+ matching_diffs,
100+ total_diffs,
101+ "matching diffs {} == total diffs {} [{:.2} %]\n \n {}" ,
102+ matching_diffs,
103+ total_diffs,
104+ ( ( matching_diffs as f32 ) / ( total_diffs as f32 ) * 100.0 ) ,
105+ {
106+ let first_non_matching_diff = diffs
107+ . iter( )
108+ . find( |( _, _, actual_matches_baseline, _) | !actual_matches_baseline)
109+ . expect( "at least one non-matching diff to be there" ) ;
110+
111+ format!(
112+ "affected baseline: `{}`\n \n {}" ,
113+ first_non_matching_diff. 3 ,
114+ StrComparison :: new( & first_non_matching_diff. 0 , & first_non_matching_diff. 1 )
115+ )
116+ }
117+ ) ;
118+
119+ Ok ( ( ) )
120+ }
121+
122+ fn tokens_for_diffing ( data : & [ u8 ] ) -> impl gix_diff:: blob:: intern:: TokenSource < Token = & [ u8 ] > {
123+ gix_diff:: blob:: sources:: byte_lines ( data)
124+ }
125+
126+ #[ test]
127+ fn baseline_v2 ( ) -> gix_testtools:: Result {
128+ use gix_diff:: blob:: v2:: { Algorithm , BasicLineDiffPrinter , Diff , InternedInput , UnifiedDiffConfig } ;
129+
8130 let worktree_path = gix_testtools:: scripted_fixture_read_only_standalone ( "make_diff_for_sliders_repo.sh" ) ?;
9131 let asset_dir = worktree_path. join ( "assets" ) ;
10132
@@ -108,7 +230,7 @@ mod baseline {
108230 use gix_object:: bstr:: ByteSlice ;
109231 use std:: iter:: Peekable ;
110232
111- use gix_diff:: blob:: unified_diff:: HunkHeader ;
233+ use gix_diff:: blob:: unified_diff:: { ConsumeHunk , HunkHeader } ;
112234 use gix_object:: bstr:: { self , BString } ;
113235
114236 static START_OF_HEADER : & [ u8 ; 4 ] = b"@@ -" ;
@@ -119,6 +241,47 @@ mod baseline {
119241 pub lines : BString ,
120242 }
121243
244+ pub struct DiffHunkRecorder {
245+ inner : Vec < DiffHunk > ,
246+ }
247+
248+ impl DiffHunkRecorder {
249+ pub fn new ( ) -> Self {
250+ Self { inner : Vec :: new ( ) }
251+ }
252+ }
253+
254+ impl ConsumeHunk for DiffHunkRecorder {
255+ type Out = Vec < DiffHunk > ;
256+
257+ fn consume_hunk (
258+ & mut self ,
259+ header : HunkHeader ,
260+ lines : & [ ( gix_diff:: blob:: unified_diff:: DiffLineKind , & [ u8 ] ) ] ,
261+ ) -> std:: io:: Result < ( ) > {
262+ let mut buf = Vec :: new ( ) ;
263+
264+ for & ( kind, line) in lines {
265+ buf. push ( kind. to_prefix ( ) as u8 ) ;
266+ buf. extend_from_slice ( line) ;
267+ buf. push ( b'\n' ) ;
268+ }
269+
270+ let diff_hunk = DiffHunk {
271+ header,
272+ lines : buf. into ( ) ,
273+ } ;
274+
275+ self . inner . push ( diff_hunk) ;
276+
277+ Ok ( ( ) )
278+ }
279+
280+ fn finish ( self ) -> Self :: Out {
281+ self . inner
282+ }
283+ }
284+
122285 type Lines < ' a > = Peekable < bstr:: Lines < ' a > > ;
123286
124287 pub struct Baseline < ' a > {
0 commit comments