Merge branch 'jk/dont-count-existing-objects-twice'
[git] / t / t8014-blame-ignore-fuzzy.sh
1 #!/bin/sh
2
3 test_description='git blame ignore fuzzy heuristic'
4 . ./test-lib.sh
5
6 pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/'
7
8 # Each test is composed of 4 variables:
9 # titleN - the test name
10 # aN - the initial content
11 # bN - the final content
12 # expectedN - the line numbers from aN that we expect git blame
13 #             on bN to identify, or "Final" if bN itself should
14 #             be identified as the origin of that line.
15
16 # We start at test 2 because setup will show as test 1
17 title2="Regression test for partially overlapping search ranges"
18 cat <<EOF >a2
19 1
20 2
21 3
22 abcdef
23 5
24 6
25 7
26 ijkl
27 9
28 10
29 11
30 pqrs
31 13
32 14
33 15
34 wxyz
35 17
36 18
37 19
38 EOF
39 cat <<EOF >b2
40 abcde
41 ijk
42 pqr
43 wxy
44 EOF
45 cat <<EOF >expected2
46 4
47 8
48 12
49 16
50 EOF
51
52 title3="Combine 3 lines into 2"
53 cat <<EOF >a3
54 if ((maxgrow==0) ||
55         ( single_line_field && (field->dcols < maxgrow)) ||
56         (!single_line_field && (field->drows < maxgrow)))
57 EOF
58 cat <<EOF >b3
59 if ((maxgrow == 0) || (single_line_field && (field->dcols < maxgrow)) ||
60         (!single_line_field && (field->drows < maxgrow))) {
61 EOF
62 cat <<EOF >expected3
63 2
64 3
65 EOF
66
67 title4="Add curly brackets"
68 cat <<EOF >a4
69         if (rows) *rows = field->rows;
70         if (cols) *cols = field->cols;
71         if (frow) *frow = field->frow;
72         if (fcol) *fcol = field->fcol;
73 EOF
74 cat <<EOF >b4
75         if (rows) {
76                 *rows = field->rows;
77         }
78         if (cols) {
79                 *cols = field->cols;
80         }
81         if (frow) {
82                 *frow = field->frow;
83         }
84         if (fcol) {
85                 *fcol = field->fcol;
86         }
87 EOF
88 cat <<EOF >expected4
89 1
90 1
91 Final
92 2
93 2
94 Final
95 3
96 3
97 Final
98 4
99 4
100 Final
101 EOF
102
103
104 title5="Combine many lines and change case"
105 cat <<EOF >a5
106 for(row=0,pBuffer=field->buf;
107         row<height;
108         row++,pBuffer+=width )
109 {
110         if ((len = (int)( After_End_Of_Data( pBuffer, width ) - pBuffer )) > 0)
111         {
112                 wmove( win, row, 0 );
113                 waddnstr( win, pBuffer, len );
114 EOF
115 cat <<EOF >b5
116 for (Row = 0, PBuffer = field->buf; Row < Height; Row++, PBuffer += Width) {
117         if ((Len = (int)(afterEndOfData(PBuffer, Width) - PBuffer)) > 0) {
118                 wmove(win, Row, 0);
119                 waddnstr(win, PBuffer, Len);
120 EOF
121 cat <<EOF >expected5
122 1
123 5
124 7
125 8
126 EOF
127
128 title6="Rename and combine lines"
129 cat <<EOF >a6
130 bool need_visual_update = ((form != (FORM *)0)      &&
131         (form->status & _POSTED) &&
132         (form->current==field));
133
134 if (need_visual_update)
135         Synchronize_Buffer(form);
136
137 if (single_line_field)
138 {
139         growth = field->cols * amount;
140         if (field->maxgrow)
141                 growth = Minimum(field->maxgrow - field->dcols,growth);
142         field->dcols += growth;
143         if (field->dcols == field->maxgrow)
144 EOF
145 cat <<EOF >b6
146 bool NeedVisualUpdate = ((Form != (FORM *)0) && (Form->status & _POSTED) &&
147         (Form->current == field));
148
149 if (NeedVisualUpdate) {
150         synchronizeBuffer(Form);
151 }
152
153 if (SingleLineField) {
154         Growth = field->cols * amount;
155         if (field->maxgrow) {
156                 Growth = Minimum(field->maxgrow - field->dcols, Growth);
157         }
158         field->dcols += Growth;
159         if (field->dcols == field->maxgrow) {
160 EOF
161 cat <<EOF >expected6
162 1
163 3
164 4
165 5
166 6
167 Final
168 7
169 8
170 10
171 11
172 12
173 Final
174 13
175 14
176 EOF
177
178 # Both lines match identically so position must be used to tie-break.
179 title7="Same line twice"
180 cat <<EOF >a7
181 abc
182 abc
183 EOF
184 cat <<EOF >b7
185 abcd
186 abcd
187 EOF
188 cat <<EOF >expected7
189 1
190 2
191 EOF
192
193 title8="Enforce line order"
194 cat <<EOF >a8
195 abcdef
196 ghijkl
197 ab
198 EOF
199 cat <<EOF >b8
200 ghijk
201 abcd
202 EOF
203 cat <<EOF >expected8
204 2
205 3
206 EOF
207
208 title9="Expand lines and rename variables"
209 cat <<EOF >a9
210 int myFunction(int ArgumentOne, Thing *ArgTwo, Blah XuglyBug) {
211         Squiggle FabulousResult = squargle(ArgumentOne, *ArgTwo,
212                 XuglyBug) + EwwwGlobalWithAReallyLongNameYepTooLong;
213         return FabulousResult * 42;
214 }
215 EOF
216 cat <<EOF >b9
217 int myFunction(int argument_one, Thing *arg_asdfgh,
218         Blah xugly_bug) {
219         Squiggle fabulous_result = squargle(argument_one,
220                 *arg_asdfgh, xugly_bug)
221                 + g_ewww_global_with_a_really_long_name_yep_too_long;
222         return fabulous_result * 42;
223 }
224 EOF
225 cat <<EOF >expected9
226 1
227 1
228 2
229 3
230 3
231 4
232 5
233 EOF
234
235 title10="Two close matches versus one less close match"
236 cat <<EOF >a10
237 abcdef
238 abcdef
239 ghijkl
240 EOF
241 cat <<EOF >b10
242 gh
243 abcdefx
244 EOF
245 cat <<EOF >expected10
246 Final
247 2
248 EOF
249
250 # The first line of b matches best with the last line of a, but the overall
251 # match is better if we match it with the first line of a.
252 title11="Piggy in the middle"
253 cat <<EOF >a11
254 abcdefg
255 ijklmn
256 abcdefgh
257 EOF
258 cat <<EOF >b11
259 abcdefghx
260 ijklm
261 EOF
262 cat <<EOF >expected11
263 1
264 2
265 EOF
266
267 title12="No trailing newline"
268 printf "abc\ndef" >a12
269 printf "abx\nstu" >b12
270 cat <<EOF >expected12
271 1
272 Final
273 EOF
274
275 title13="Reorder includes"
276 cat <<EOF >a13
277 #include "c.h"
278 #include "b.h"
279 #include "a.h"
280 #include "e.h"
281 #include "d.h"
282 EOF
283 cat <<EOF >b13
284 #include "a.h"
285 #include "b.h"
286 #include "c.h"
287 #include "d.h"
288 #include "e.h"
289 EOF
290 cat <<EOF >expected13
291 3
292 2
293 1
294 5
295 4
296 EOF
297
298 last_test=13
299
300 test_expect_success setup '
301         for i in $(test_seq 2 $last_test)
302         do
303                 # Append each line in a separate commit to make it easy to
304                 # check which original line the blame output relates to.
305
306                 line_count=0 &&
307                 while IFS= read line
308                 do
309                         line_count=$((line_count+1)) &&
310                         echo "$line" >>"$i" &&
311                         git add "$i" &&
312                         test_tick &&
313                         GIT_AUTHOR_NAME="$line_count" git commit -m "$line_count"
314                 done <"a$i"
315         done &&
316
317         for i in $(test_seq 2 $last_test)
318         do
319                 # Overwrite the files with the final content.
320                 cp b$i $i &&
321                 git add $i
322         done &&
323         test_tick &&
324
325         # Commit the final content all at once so it can all be
326         # referred to with the same commit ID.
327         GIT_AUTHOR_NAME=Final git commit -m Final &&
328
329         IGNOREME=$(git rev-parse HEAD)
330 '
331
332 for i in $(test_seq 2 $last_test); do
333         eval title="\$title$i"
334         test_expect_success "$title" \
335         "git blame -M9 --ignore-rev $IGNOREME $i >output &&
336         sed -e \"$pick_author\" output >actual &&
337         test_cmp expected$i actual"
338 done
339
340 # This invoked a null pointer dereference when the chunk callback was called
341 # with a zero length parent chunk and there were no more suspects.
342 test_expect_success 'Diff chunks with no suspects' '
343         test_write_lines xy1 A B C xy1 >file &&
344         git add file &&
345         test_tick &&
346         GIT_AUTHOR_NAME=1 git commit -m 1 &&
347
348         test_write_lines xy2 A B xy2 C xy2 >file &&
349         git add file &&
350         test_tick &&
351         GIT_AUTHOR_NAME=2 git commit -m 2 &&
352         REV_2=$(git rev-parse HEAD) &&
353
354         test_write_lines xy3 A >file &&
355         git add file &&
356         test_tick &&
357         GIT_AUTHOR_NAME=3 git commit -m 3 &&
358         REV_3=$(git rev-parse HEAD) &&
359
360         test_write_lines 1 1 >expected &&
361
362         git blame --ignore-rev $REV_2 --ignore-rev $REV_3 file >output &&
363         sed -e "$pick_author" output >actual &&
364
365         test_cmp expected actual
366         '
367
368 test_expect_success 'position matching' '
369         test_write_lines abc def >file2 &&
370         git add file2 &&
371         test_tick &&
372         GIT_AUTHOR_NAME=1 git commit -m 1 &&
373
374         test_write_lines abc def abc def >file2 &&
375         git add file2 &&
376         test_tick &&
377         GIT_AUTHOR_NAME=2 git commit -m 2 &&
378
379         test_write_lines abcx defx abcx defx >file2 &&
380         git add file2 &&
381         test_tick &&
382         GIT_AUTHOR_NAME=3 git commit -m 3 &&
383         REV_3=$(git rev-parse HEAD) &&
384
385         test_write_lines abcy defy abcx defx >file2 &&
386         git add file2 &&
387         test_tick &&
388         GIT_AUTHOR_NAME=4 git commit -m 4 &&
389         REV_4=$(git rev-parse HEAD) &&
390
391         test_write_lines 1 1 2 2 >expected &&
392
393         git blame --ignore-rev $REV_3 --ignore-rev $REV_4 file2 >output &&
394         sed -e "$pick_author" output >actual &&
395
396         test_cmp expected actual
397         '
398
399 # This fails if each blame entry is processed independently instead of
400 # processing each diff change in full.
401 test_expect_success 'preserve order' '
402         test_write_lines bcde >file3 &&
403         git add file3 &&
404         test_tick &&
405         GIT_AUTHOR_NAME=1 git commit -m 1 &&
406
407         test_write_lines bcde fghij >file3 &&
408         git add file3 &&
409         test_tick &&
410         GIT_AUTHOR_NAME=2 git commit -m 2 &&
411
412         test_write_lines bcde fghij abcd >file3 &&
413         git add file3 &&
414         test_tick &&
415         GIT_AUTHOR_NAME=3 git commit -m 3 &&
416
417         test_write_lines abcdx fghijx bcdex >file3 &&
418         git add file3 &&
419         test_tick &&
420         GIT_AUTHOR_NAME=4 git commit -m 4 &&
421         REV_4=$(git rev-parse HEAD) &&
422
423         test_write_lines abcdx fghijy bcdex >file3 &&
424         git add file3 &&
425         test_tick &&
426         GIT_AUTHOR_NAME=5 git commit -m 5 &&
427         REV_5=$(git rev-parse HEAD) &&
428
429         test_write_lines 1 2 3 >expected &&
430
431         git blame --ignore-rev $REV_4 --ignore-rev $REV_5 file3 >output &&
432         sed -e "$pick_author" output >actual &&
433
434         test_cmp expected actual
435         '
436
437 test_done