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 ;
42use gix_testtools:: bstr:: { BString , ByteVec } ;
53use 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
126168mod 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