| 1 | #!/bin/sh |
| 2 | |
| 3 | test_description='Test diff-highlight' |
| 4 | |
| 5 | CURR_DIR=$(pwd) |
| 6 | TEST_OUTPUT_DIRECTORY=$(pwd) |
| 7 | TEST_DIRECTORY="$CURR_DIR"/../../../t |
| 8 | DIFF_HIGHLIGHT="$CURR_DIR"/../diff-highlight |
| 9 | |
| 10 | GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master |
| 11 | export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME |
| 12 | . "$TEST_DIRECTORY"/test-lib.sh |
| 13 | |
| 14 | if ! test_have_prereq PERL |
| 15 | then |
| 16 | skip_all='skipping diff-highlight tests; perl not available' |
| 17 | test_done |
| 18 | fi |
| 19 | |
| 20 | # dh_test is a test helper function which takes 3 file names as parameters. The |
| 21 | # first 2 files are used to generate diff and commit output, which is then |
| 22 | # piped through diff-highlight. The 3rd file should contain the expected output |
| 23 | # of diff-highlight (minus the diff/commit header, ie. everything after and |
| 24 | # including the first @@ line). |
| 25 | dh_test () { |
| 26 | a="$1" b="$2" && |
| 27 | |
| 28 | cat >patch.exp && |
| 29 | |
| 30 | { |
| 31 | cat "$a" >file && |
| 32 | git add file && |
| 33 | git commit -m "Add a file" && |
| 34 | |
| 35 | cat "$b" >file && |
| 36 | git diff file >diff.raw && |
| 37 | git commit -a -m "Update a file" && |
| 38 | git show >commit.raw |
| 39 | } >/dev/null && |
| 40 | |
| 41 | "$DIFF_HIGHLIGHT" <diff.raw >diff.hi && |
| 42 | test_strip_patch_header <diff.hi | test_decode_color >diff.act && |
| 43 | "$DIFF_HIGHLIGHT" <commit.raw >commit.hi && |
| 44 | test_strip_patch_header <commit.hi | test_decode_color >commit.act && |
| 45 | test_cmp patch.exp diff.act && |
| 46 | test_cmp patch.exp commit.act |
| 47 | } |
| 48 | |
| 49 | test_strip_patch_header () { |
| 50 | sed -n '/^@@/,$p' $* |
| 51 | } |
| 52 | |
| 53 | # dh_test_setup_history generates a contrived graph such that we have at least |
| 54 | # 1 nesting (E) and 2 nestings (F). |
| 55 | # |
| 56 | # A---B master |
| 57 | # / |
| 58 | # D---E---F branch |
| 59 | # |
| 60 | # git log --all --graph |
| 61 | # * commit |
| 62 | # | B |
| 63 | # | * commit |
| 64 | # | | F |
| 65 | # * | commit |
| 66 | # | | A |
| 67 | # | * commit |
| 68 | # |/ |
| 69 | # | E |
| 70 | # * commit |
| 71 | # D |
| 72 | # |
| 73 | dh_test_setup_history () { |
| 74 | echo file1 >file && |
| 75 | git add file && |
| 76 | test_tick && |
| 77 | git commit -m "D" && |
| 78 | |
| 79 | git checkout -b branch && |
| 80 | echo file2 >file && |
| 81 | test_tick && |
| 82 | git commit -a -m "E" && |
| 83 | |
| 84 | git checkout master && |
| 85 | echo file2 >file && |
| 86 | test_tick && |
| 87 | git commit -a -m "A" && |
| 88 | |
| 89 | git checkout branch && |
| 90 | echo file3 >file && |
| 91 | test_tick && |
| 92 | git commit -a -m "F" && |
| 93 | |
| 94 | git checkout master && |
| 95 | echo file3 >file && |
| 96 | test_tick && |
| 97 | git commit -a -m "B" |
| 98 | } |
| 99 | |
| 100 | left_trim () { |
| 101 | "$PERL_PATH" -pe 's/^\s+//' |
| 102 | } |
| 103 | |
| 104 | trim_graph () { |
| 105 | # graphs start with * or | |
| 106 | # followed by a space or / or \ |
| 107 | "$PERL_PATH" -pe 's@^((\*|\|)( |/|\\))+@@' |
| 108 | } |
| 109 | |
| 110 | test_expect_success 'diff-highlight highlights the beginning of a line' ' |
| 111 | cat >a <<-\EOF && |
| 112 | aaa |
| 113 | bbb |
| 114 | ccc |
| 115 | EOF |
| 116 | |
| 117 | cat >b <<-\EOF && |
| 118 | aaa |
| 119 | 0bb |
| 120 | ccc |
| 121 | EOF |
| 122 | |
| 123 | dh_test a b <<-EOF |
| 124 | @@ -1,3 +1,3 @@ |
| 125 | aaa |
| 126 | -<REVERSE>b<NOREVERSE>bb |
| 127 | +<REVERSE>0<NOREVERSE>bb |
| 128 | ccc |
| 129 | EOF |
| 130 | ' |
| 131 | |
| 132 | test_expect_success 'diff-highlight highlights the end of a line' ' |
| 133 | cat >a <<-\EOF && |
| 134 | aaa |
| 135 | bbb |
| 136 | ccc |
| 137 | EOF |
| 138 | |
| 139 | cat >b <<-\EOF && |
| 140 | aaa |
| 141 | bb0 |
| 142 | ccc |
| 143 | EOF |
| 144 | |
| 145 | dh_test a b <<-EOF |
| 146 | @@ -1,3 +1,3 @@ |
| 147 | aaa |
| 148 | -bb<REVERSE>b<NOREVERSE> |
| 149 | +bb<REVERSE>0<NOREVERSE> |
| 150 | ccc |
| 151 | EOF |
| 152 | ' |
| 153 | |
| 154 | test_expect_success 'diff-highlight highlights the middle of a line' ' |
| 155 | cat >a <<-\EOF && |
| 156 | aaa |
| 157 | bbb |
| 158 | ccc |
| 159 | EOF |
| 160 | |
| 161 | cat >b <<-\EOF && |
| 162 | aaa |
| 163 | b0b |
| 164 | ccc |
| 165 | EOF |
| 166 | |
| 167 | dh_test a b <<-EOF |
| 168 | @@ -1,3 +1,3 @@ |
| 169 | aaa |
| 170 | -b<REVERSE>b<NOREVERSE>b |
| 171 | +b<REVERSE>0<NOREVERSE>b |
| 172 | ccc |
| 173 | EOF |
| 174 | ' |
| 175 | |
| 176 | test_expect_success 'diff-highlight does not highlight whole line' ' |
| 177 | cat >a <<-\EOF && |
| 178 | aaa |
| 179 | bbb |
| 180 | ccc |
| 181 | EOF |
| 182 | |
| 183 | cat >b <<-\EOF && |
| 184 | aaa |
| 185 | 000 |
| 186 | ccc |
| 187 | EOF |
| 188 | |
| 189 | dh_test a b <<-EOF |
| 190 | @@ -1,3 +1,3 @@ |
| 191 | aaa |
| 192 | -bbb |
| 193 | +000 |
| 194 | ccc |
| 195 | EOF |
| 196 | ' |
| 197 | |
| 198 | test_expect_failure 'diff-highlight highlights mismatched hunk size' ' |
| 199 | cat >a <<-\EOF && |
| 200 | aaa |
| 201 | bbb |
| 202 | EOF |
| 203 | |
| 204 | cat >b <<-\EOF && |
| 205 | aaa |
| 206 | b0b |
| 207 | ccc |
| 208 | EOF |
| 209 | |
| 210 | dh_test a b <<-EOF |
| 211 | @@ -1,3 +1,3 @@ |
| 212 | aaa |
| 213 | -b<REVERSE>b<NOREVERSE>b |
| 214 | +b<REVERSE>0<NOREVERSE>b |
| 215 | +ccc |
| 216 | EOF |
| 217 | ' |
| 218 | |
| 219 | # These two code points share the same leading byte in UTF-8 representation; |
| 220 | # a naive byte-wise diff would highlight only the second byte. |
| 221 | # |
| 222 | # - U+00f3 ("o" with acute) |
| 223 | o_accent=$(printf '\303\263') |
| 224 | # - U+00f8 ("o" with stroke) |
| 225 | o_stroke=$(printf '\303\270') |
| 226 | |
| 227 | test_expect_success 'diff-highlight treats multibyte utf-8 as a unit' ' |
| 228 | echo "unic${o_accent}de" >a && |
| 229 | echo "unic${o_stroke}de" >b && |
| 230 | dh_test a b <<-EOF |
| 231 | @@ -1 +1 @@ |
| 232 | -unic<REVERSE>${o_accent}<NOREVERSE>de |
| 233 | +unic<REVERSE>${o_stroke}<NOREVERSE>de |
| 234 | EOF |
| 235 | ' |
| 236 | |
| 237 | # Unlike the UTF-8 above, these are combining code points which are meant |
| 238 | # to modify the character preceding them: |
| 239 | # |
| 240 | # - U+0301 (combining acute accent) |
| 241 | combine_accent=$(printf '\314\201') |
| 242 | # - U+0302 (combining circumflex) |
| 243 | combine_circum=$(printf '\314\202') |
| 244 | |
| 245 | test_expect_failure 'diff-highlight treats combining code points as a unit' ' |
| 246 | echo "unico${combine_accent}de" >a && |
| 247 | echo "unico${combine_circum}de" >b && |
| 248 | dh_test a b <<-EOF |
| 249 | @@ -1 +1 @@ |
| 250 | -unic<REVERSE>o${combine_accent}<NOREVERSE>de |
| 251 | +unic<REVERSE>o${combine_circum}<NOREVERSE>de |
| 252 | EOF |
| 253 | ' |
| 254 | |
| 255 | test_expect_success 'diff-highlight works with the --graph option' ' |
| 256 | dh_test_setup_history && |
| 257 | |
| 258 | # date-order so that the commits are interleaved for both |
| 259 | # trim graph elements so we can do a diff |
| 260 | # trim leading space because our trim_graph is not perfect |
| 261 | git log --branches -p --date-order | |
| 262 | "$DIFF_HIGHLIGHT" | left_trim >graph.exp && |
| 263 | git log --branches -p --date-order --graph | |
| 264 | "$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph.act && |
| 265 | test_cmp graph.exp graph.act |
| 266 | ' |
| 267 | |
| 268 | # Just reuse the previous graph test, but with --color. Our trimming |
| 269 | # doesn't know about color, so just sanity check that something got |
| 270 | # highlighted. |
| 271 | test_expect_success 'diff-highlight works with color graph' ' |
| 272 | git log --branches -p --date-order --graph --color | |
| 273 | "$DIFF_HIGHLIGHT" | trim_graph | left_trim >graph && |
| 274 | grep "\[7m" graph |
| 275 | ' |
| 276 | |
| 277 | # Most combined diffs won't meet diff-highlight's line-number filter. So we |
| 278 | # create one here where one side drops a line and the other modifies it. That |
| 279 | # should result in a diff like: |
| 280 | # |
| 281 | # - modified content |
| 282 | # ++resolved content |
| 283 | # |
| 284 | # which naively looks like one side added "+resolved". |
| 285 | test_expect_success 'diff-highlight ignores combined diffs' ' |
| 286 | echo "content" >file && |
| 287 | git add file && |
| 288 | git commit -m base && |
| 289 | |
| 290 | >file && |
| 291 | git commit -am master && |
| 292 | |
| 293 | git checkout -b other HEAD^ && |
| 294 | echo "modified content" >file && |
| 295 | git commit -am other && |
| 296 | |
| 297 | test_must_fail git merge master && |
| 298 | echo "resolved content" >file && |
| 299 | git commit -am resolved && |
| 300 | |
| 301 | cat >expect <<-\EOF && |
| 302 | --- a/file |
| 303 | +++ b/file |
| 304 | @@@ -1,1 -1,0 +1,1 @@@ |
| 305 | - modified content |
| 306 | ++resolved content |
| 307 | EOF |
| 308 | |
| 309 | git show -c | "$DIFF_HIGHLIGHT" >actual.raw && |
| 310 | sed -n "/^---/,\$p" <actual.raw >actual && |
| 311 | test_cmp expect actual |
| 312 | ' |
| 313 | |
| 314 | test_expect_success 'diff-highlight handles --graph with leading dash' ' |
| 315 | cat >file <<-\EOF && |
| 316 | before |
| 317 | the old line |
| 318 | -leading dash |
| 319 | EOF |
| 320 | git add file && |
| 321 | git commit -m before && |
| 322 | |
| 323 | sed s/old/new/ <file >file.tmp && |
| 324 | mv file.tmp file && |
| 325 | git add file && |
| 326 | git commit -m after && |
| 327 | |
| 328 | cat >expect <<-EOF && |
| 329 | --- a/file |
| 330 | +++ b/file |
| 331 | @@ -1,3 +1,3 @@ |
| 332 | before |
| 333 | -the <REVERSE>old<NOREVERSE> line |
| 334 | +the <REVERSE>new<NOREVERSE> line |
| 335 | -leading dash |
| 336 | EOF |
| 337 | git log --graph -p -1 | "$DIFF_HIGHLIGHT" >actual.raw && |
| 338 | trim_graph <actual.raw | sed -n "/^---/,\$p" | test_decode_color >actual && |
| 339 | test_cmp expect actual |
| 340 | ' |
| 341 | |
| 342 | test_expect_success 'highlight diff that removes final newline' ' |
| 343 | printf "content\n" >a && |
| 344 | printf "content" >b && |
| 345 | dh_test a b <<-\EOF |
| 346 | @@ -1 +1 @@ |
| 347 | -content |
| 348 | +content |
| 349 | \ No newline at end of file |
| 350 | EOF |
| 351 | ' |
| 352 | |
| 353 | test_expect_success 'configure set/reset colors' ' |
| 354 | test_config color.diff-highlight.oldhighlight bold && |
| 355 | test_config color.diff-highlight.oldreset nobold && |
| 356 | test_config color.diff-highlight.newhighlight italic && |
| 357 | test_config color.diff-highlight.newreset noitalic && |
| 358 | echo "prefix a suffix" >a && |
| 359 | echo "prefix b suffix" >b && |
| 360 | dh_test a b <<-\EOF |
| 361 | @@ -1 +1 @@ |
| 362 | -prefix <BOLD>a<NORMAL_INTENSITY> suffix |
| 363 | +prefix <ITALIC>b<NOITALIC> suffix |
| 364 | EOF |
| 365 | ' |
| 366 | |
| 367 | test_expect_success 'configure normal/highlight colors' ' |
| 368 | test_config color.diff-highlight.oldnormal red && |
| 369 | test_config color.diff-highlight.oldhighlight magenta && |
| 370 | test_config color.diff-highlight.newnormal green && |
| 371 | test_config color.diff-highlight.newhighlight yellow && |
| 372 | echo "prefix a suffix" >a && |
| 373 | echo "prefix b suffix" >b && |
| 374 | dh_test a b <<-\EOF |
| 375 | @@ -1 +1 @@ |
| 376 | <RED>-prefix <RESET><MAGENTA>a<RESET><RED> suffix<RESET> |
| 377 | <GREEN>+prefix <RESET><YELLOW>b<RESET><GREEN> suffix<RESET> |
| 378 | EOF |
| 379 | ' |
| 380 | |
| 381 | test_done |