t / t8014-blame-ignore-fuzzy.shon commit blame: add a fingerprint heuristic to match ignored lines (1d028dc)
   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