Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='git blame ignore fuzzy heuristic' |
| 4 | . ./test-lib.sh |
| 5 | |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 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 |
Elijah Newren | 6d12b53 | 2020-07-28 20:45:38 +0000 | [diff] [blame] | 251 | # match is better if we match it with the first line of a. |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 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 ' |
Michael Platings | 78fafbb | 2019-06-30 19:17:32 +0100 | [diff] [blame] | 301 | for i in $(test_seq 2 $last_test) |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 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 && |
Michael Platings | 78fafbb | 2019-06-30 19:17:32 +0100 | [diff] [blame] | 307 | while IFS= read line |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 308 | do |
| 309 | line_count=$((line_count+1)) && |
| 310 | echo "$line" >>"$i" && |
| 311 | git add "$i" && |
| 312 | test_tick && |
Eric Sunshine | 0c51d6b | 2021-12-09 00:11:15 -0500 | [diff] [blame] | 313 | GIT_AUTHOR_NAME="$line_count" git commit -m "$line_count" || return 1 |
Michael Platings | 78fafbb | 2019-06-30 19:17:32 +0100 | [diff] [blame] | 314 | done <"a$i" |
| 315 | done && |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 316 | |
Michael Platings | 78fafbb | 2019-06-30 19:17:32 +0100 | [diff] [blame] | 317 | for i in $(test_seq 2 $last_test) |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 318 | do |
| 319 | # Overwrite the files with the final content. |
| 320 | cp b$i $i && |
Eric Sunshine | 0c51d6b | 2021-12-09 00:11:15 -0500 | [diff] [blame] | 321 | git add $i || return 1 |
Michael Platings | 78fafbb | 2019-06-30 19:17:32 +0100 | [diff] [blame] | 322 | done && |
Michael Platings | 1d028dc | 2019-06-20 12:38:18 -0400 | [diff] [blame] | 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 |