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