1#!/usr/bin/perl -w 2# 3# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 14# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND 15# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR 18# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 25# Unit tests of parseGitDiffHeader(). 26 27use strict; 28use warnings; 29 30use Test::More; 31use VCSUtils; 32 33# The array of test cases. 34my @testCaseHashRefs = ( 35{ # New test 36 diffName => "Modified file", 37 inputText => <<'END', 38diff --git a/foo.h b/foo.h 39index f5d5e74..3b6aa92 100644 40--- a/foo.h 41+++ b/foo.h 42@@ -1 +1 @@ 43-file contents 44+new file contents 45END 46 expectedReturn => [ 47{ 48 svnConvertedText => <<'END', 49Index: foo.h 50index f5d5e74..3b6aa92 100644 51--- foo.h 52+++ foo.h 53END 54 indexPath => "foo.h", 55}, 56"@@ -1 +1 @@\n"], 57 expectedNextLine => "-file contents\n", 58}, 59{ # New test 60 diffName => "new file", 61 inputText => <<'END', 62diff --git a/foo.h b/foo.h 63new file mode 100644 64index 0000000..3c9f114 65--- /dev/null 66+++ b/foo.h 67@@ -0,0 +1,34 @@ 68+<html> 69END 70 expectedReturn => [ 71{ 72 svnConvertedText => <<'END', 73Index: foo.h 74new file mode 100644 75index 0000000..3c9f114 76--- foo.h 77+++ foo.h 78END 79 indexPath => "foo.h", 80 isNew => 1, 81}, 82"@@ -0,0 +1,34 @@\n"], 83 expectedNextLine => "+<html>\n", 84}, 85{ # New test 86 diffName => "file deletion", 87 inputText => <<'END', 88diff --git a/foo b/foo 89deleted file mode 100644 90index 1e50d1d..0000000 91--- a/foo 92+++ /dev/null 93@@ -1,1 +0,0 @@ 94-line1 95diff --git a/configure.ac b/configure.ac 96index d45dd40..3494526 100644 97END 98 expectedReturn => [ 99{ 100 svnConvertedText => <<'END', 101Index: foo 102deleted file mode 100644 103index 1e50d1d..0000000 104--- foo 105+++ foo 106END 107 indexPath => "foo", 108 isDeletion => 1, 109}, 110"@@ -1,1 +0,0 @@\n"], 111 expectedNextLine => "-line1\n", 112}, 113{ # New test 114 diffName => "using --no-prefix", 115 inputText => <<'END', 116diff --git foo.h foo.h 117index c925780..9e65c43 100644 118--- foo.h 119+++ foo.h 120@@ -1,3 +1,17 @@ 121+contents 122END 123 expectedReturn => [ 124{ 125 svnConvertedText => <<'END', 126Index: foo.h 127index c925780..9e65c43 100644 128--- foo.h 129+++ foo.h 130END 131 indexPath => "foo.h", 132}, 133"@@ -1,3 +1,17 @@\n"], 134 expectedNextLine => "+contents\n", 135}, 136#### 137# Copy operations 138## 139{ # New test 140 diffName => "copy (with similarity index 100%)", 141 inputText => <<'END', 142diff --git a/foo b/foo_new 143similarity index 100% 144copy from foo 145copy to foo_new 146diff --git a/bar b/bar 147index d45dd40..3494526 100644 148END 149 expectedReturn => [ 150{ 151 svnConvertedText => <<'END', 152Index: foo_new 153similarity index 100% 154copy from foo 155copy to foo_new 156END 157 copiedFromPath => "foo", 158 indexPath => "foo_new", 159}, 160"diff --git a/bar b/bar\n"], 161 expectedNextLine => "index d45dd40..3494526 100644\n", 162}, 163{ # New test 164 diffName => "copy (with similarity index < 100%)", 165 inputText => <<'END', 166diff --git a/foo b/foo_new 167similarity index 99% 168copy from foo 169copy to foo_new 170diff --git a/bar b/bar 171index d45dd40..3494526 100644 172END 173 expectedReturn => [ 174{ 175 svnConvertedText => <<'END', 176Index: foo_new 177similarity index 99% 178copy from foo 179copy to foo_new 180END 181 copiedFromPath => "foo", 182 indexPath => "foo_new", 183 isCopyWithChanges => 1, 184}, 185"diff --git a/bar b/bar\n"], 186 expectedNextLine => "index d45dd40..3494526 100644\n", 187}, 188{ # New test 189 diffName => "rename (with similarity index 100%)", 190 inputText => <<'END', 191diff --git a/foo b/foo_new 192similarity index 100% 193rename from foo 194rename to foo_new 195diff --git a/bar b/bar 196index d45dd40..3494526 100644 197END 198 expectedReturn => [ 199{ 200 svnConvertedText => <<'END', 201Index: foo_new 202similarity index 100% 203rename from foo 204rename to foo_new 205END 206 copiedFromPath => "foo", 207 indexPath => "foo_new", 208 shouldDeleteSource => 1, 209}, 210"diff --git a/bar b/bar\n"], 211 expectedNextLine => "index d45dd40..3494526 100644\n", 212}, 213{ # New test 214 diffName => "rename (with similarity index < 100%)", 215 inputText => <<'END', 216diff --git a/foo b/foo_new 217similarity index 99% 218rename from foo 219rename to foo_new 220index 1e50d1d..1459d21 100644 221--- a/foo 222+++ b/foo_new 223@@ -15,3 +15,4 @@ release r deployment dep deploy: 224 line1 225 line2 226 line3 227+line4 228diff --git a/bar b/bar 229index d45dd40..3494526 100644 230END 231 expectedReturn => [ 232{ 233 svnConvertedText => <<'END', 234Index: foo_new 235similarity index 99% 236rename from foo 237rename to foo_new 238index 1e50d1d..1459d21 100644 239--- foo_new 240+++ foo_new 241END 242 copiedFromPath => "foo", 243 indexPath => "foo_new", 244 isCopyWithChanges => 1, 245 shouldDeleteSource => 1, 246}, 247"@@ -15,3 +15,4 @@ release r deployment dep deploy:\n"], 248 expectedNextLine => " line1\n", 249}, 250{ # New test 251 diffName => "rename (with executable bit change)", 252 inputText => <<'END', 253diff --git a/foo b/foo_new 254old mode 100644 255new mode 100755 256similarity index 100% 257rename from foo 258rename to foo_new 259diff --git a/bar b/bar 260index d45dd40..3494526 100644 261END 262 expectedReturn => [ 263{ 264 svnConvertedText => <<'END', 265Index: foo_new 266old mode 100644 267new mode 100755 268similarity index 100% 269rename from foo 270rename to foo_new 271END 272 copiedFromPath => "foo", 273 executableBitDelta => 1, 274 indexPath => "foo_new", 275 isCopyWithChanges => 1, 276 shouldDeleteSource => 1, 277}, 278"diff --git a/bar b/bar\n"], 279 expectedNextLine => "index d45dd40..3494526 100644\n", 280}, 281#### 282# Binary file test cases 283## 284{ 285 # New test case 286 diffName => "New binary file", 287 inputText => <<'END', 288diff --git a/foo.gif b/foo.gif 289new file mode 100644 290index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690 291GIT binary patch 292literal 7 293OcmYex&reDa;sO8*F9L)B 294 295literal 0 296HcmV?d00001 297 298END 299 expectedReturn => [ 300{ 301 svnConvertedText => <<'END', 302Index: foo.gif 303new file mode 100644 304index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690 305GIT binary patch 306END 307 indexPath => "foo.gif", 308 isBinary => 1, 309 isNew => 1, 310}, 311"literal 7\n"], 312 expectedNextLine => "OcmYex&reDa;sO8*F9L)B\n", 313}, 314{ 315 # New test case 316 diffName => "Deleted binary file", 317 inputText => <<'END', 318diff --git a/foo.gif b/foo.gif 319deleted file mode 100644 320index 323fae0..0000000 321GIT binary patch 322literal 0 323HcmV?d00001 324 325literal 7 326OcmYex&reDa;sO8*F9L)B 327 328END 329 expectedReturn => [ 330{ 331 svnConvertedText => <<'END', 332Index: foo.gif 333deleted file mode 100644 334index 323fae0..0000000 335GIT binary patch 336END 337 indexPath => "foo.gif", 338 isBinary => 1, 339 isDeletion => 1, 340}, 341"literal 0\n"], 342 expectedNextLine => "HcmV?d00001\n", 343}, 344#### 345# Executable bit test cases 346## 347{ 348 # New test case 349 diffName => "Modified executable file", 350 inputText => <<'END', 351diff --git a/foo b/foo 352index d03e242..435ad3a 100755 353--- a/foo 354+++ b/foo 355@@ -1 +1 @@ 356-file contents 357+new file contents 358 359END 360 expectedReturn => [ 361{ 362 svnConvertedText => <<'END', 363Index: foo 364index d03e242..435ad3a 100755 365--- foo 366+++ foo 367END 368 indexPath => "foo", 369}, 370"@@ -1 +1 @@\n"], 371 expectedNextLine => "-file contents\n", 372}, 373{ 374 # New test case 375 diffName => "Making file executable (last diff)", 376 inputText => <<'END', 377diff --git a/foo.exe b/foo.exe 378old mode 100644 379new mode 100755 380END 381 expectedReturn => [ 382{ 383 svnConvertedText => <<'END', 384Index: foo.exe 385old mode 100644 386new mode 100755 387END 388 executableBitDelta => 1, 389 indexPath => "foo.exe", 390}, 391undef], 392 expectedNextLine => undef, 393}, 394{ 395 # New test case 396 diffName => "Making file executable (not last diff)", 397 inputText => <<'END', 398diff --git a/foo.exe b/foo.exe 399old mode 100644 400new mode 100755 401diff --git a/another_file.txt b/another_file.txt 402index d03e242..435ad3a 100755 403END 404 expectedReturn => [ 405{ 406 svnConvertedText => <<'END', 407Index: foo.exe 408old mode 100644 409new mode 100755 410END 411 executableBitDelta => 1, 412 indexPath => "foo.exe", 413}, 414"diff --git a/another_file.txt b/another_file.txt\n"], 415 expectedNextLine => "index d03e242..435ad3a 100755\n", 416}, 417{ 418 # New test case 419 diffName => "New executable file", 420 inputText => <<'END', 421diff --git a/foo b/foo 422new file mode 100755 423index 0000000..d03e242 424--- /dev/null 425+++ b/foo 426@@ -0,0 +1 @@ 427+file contents 428 429END 430 expectedReturn => [ 431{ 432 svnConvertedText => <<'END', 433Index: foo 434new file mode 100755 435index 0000000..d03e242 436--- foo 437+++ foo 438END 439 executableBitDelta => 1, 440 indexPath => "foo", 441 isNew => 1, 442}, 443"@@ -0,0 +1 @@\n"], 444 expectedNextLine => "+file contents\n", 445}, 446{ 447 # New test case 448 diffName => "Deleted executable file", 449 inputText => <<'END', 450diff --git a/foo b/foo 451deleted file mode 100755 452index d03e242..0000000 453--- a/foo 454+++ /dev/null 455@@ -1 +0,0 @@ 456-file contents 457 458END 459 expectedReturn => [ 460{ 461 svnConvertedText => <<'END', 462Index: foo 463deleted file mode 100755 464index d03e242..0000000 465--- foo 466+++ foo 467END 468 executableBitDelta => -1, 469 indexPath => "foo", 470 isDeletion => 1, 471}, 472"@@ -1 +0,0 @@\n"], 473 expectedNextLine => "-file contents\n", 474}, 475); 476 477my $testCasesCount = @testCaseHashRefs; 478plan(tests => 2 * $testCasesCount); # Total number of assertions. 479 480foreach my $testCase (@testCaseHashRefs) { 481 my $testNameStart = "parseGitDiffHeader(): $testCase->{diffName}: comparing"; 482 483 my $fileHandle; 484 open($fileHandle, "<", \$testCase->{inputText}); 485 my $line = <$fileHandle>; 486 487 my @got = VCSUtils::parseGitDiffHeader($fileHandle, $line); 488 my $expectedReturn = $testCase->{expectedReturn}; 489 490 is_deeply(\@got, $expectedReturn, "$testNameStart return value."); 491 492 my $gotNextLine = <$fileHandle>; 493 is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line."); 494} 495