summaryrefslogtreecommitdiffstats
path: root/Tools/Scripts/webkitperl/VCSUtils_unittest
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitperl/VCSUtils_unittest')
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl533
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/generatePatchCommand.pl87
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/mergeChangeLogs.pl336
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl1208
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl121
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl494
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl94
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffFooter.pl397
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl220
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl743
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl233
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl136
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/removeEOL.pl56
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl92
-rw-r--r--Tools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl128
15 files changed, 4878 insertions, 0 deletions
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl
new file mode 100644
index 0000000..a7282c7
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/fixChangeLogPatch.pl
@@ -0,0 +1,533 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+# Copyright (C) Research In Motion 2010. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of VCSUtils::fixChangeLogPatch().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+# The source ChangeLog for these tests is the following:
+#
+# 2009-12-22 Alice <alice@email.address>
+#
+# Reviewed by Ray.
+#
+# Changed some code on 2009-12-22.
+#
+# * File:
+# * File2:
+#
+# 2009-12-21 Alice <alice@email.address>
+#
+# Reviewed by Ray.
+#
+# Changed some code on 2009-12-21.
+#
+# * File:
+# * File2:
+
+my @testCaseHashRefs = (
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] In-place change.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,5 +1,5 @@
+ 2010-12-22 Bob <bob@email.address>
+
+- Reviewed by Sue.
++ Reviewed by Ray.
+
+ Changed some code on 2010-12-22.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,5 +1,5 @@
+ 2010-12-22 Bob <bob@email.address>
+
+- Reviewed by Sue.
++ Reviewed by Ray.
+
+ Changed some code on 2010-12-22.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] Remove first entry.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,11 +1,3 @@
+-2010-12-22 Bob <bob@email.address>
+-
+- Reviewed by Ray.
+-
+- Changed some code on 2010-12-22.
+-
+- * File:
+-
+ 2010-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,11 +1,3 @@
+-2010-12-22 Bob <bob@email.address>
+-
+- Reviewed by Ray.
+-
+- Changed some code on 2010-12-22.
+-
+- * File:
+-
+ 2010-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] Remove entry in the middle.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@@ -7,10 +7,6 @@
+
+ * File:
+
+-2010-12-22 Bob <bob@email.address>
+-
+- Changed some code on 2010-12-22.
+-
+ 2010-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@@ -7,10 +7,6 @@
+
+ * File:
+
+-2010-12-22 Bob <bob@email.address>
+-
+- Changed some code on 2010-12-22.
+-
+ 2010-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] Far apart changes (i.e. more than one chunk).",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -7,7 +7,7 @@
+
+ * File:
+
+-2010-12-22 Bob <bob@email.address>
++2010-12-22 Bobby <bob@email.address>
+
+ Changed some code on 2010-12-22.
+
+@@ -21,7 +21,7 @@
+
+ * File2:
+
+-2010-12-21 Bob <bob@email.address>
++2010-12-21 Bobby <bob@email.address>
+
+ Changed some code on 2010-12-21.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -7,7 +7,7 @@
+
+ * File:
+
+-2010-12-22 Bob <bob@email.address>
++2010-12-22 Bobby <bob@email.address>
+
+ Changed some code on 2010-12-22.
+
+@@ -21,7 +21,7 @@
+
+ * File2:
+
+-2010-12-21 Bob <bob@email.address>
++2010-12-21 Bobby <bob@email.address>
+
+ Changed some code on 2010-12-21.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] First line is new line.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,3 +1,11 @@
++2009-12-22 Bob <bob@email.address>
++
++ Reviewed by Ray.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,3 +1,11 @@
++2009-12-22 Bob <bob@email.address>
++
++ Reviewed by Ray.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] No date string.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -6,6 +6,7 @@
+
+ * File:
+ * File2:
++ * File3:
+
+ 2009-12-21 Alice <alice@email.address>
+
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -6,6 +6,7 @@
+
+ * File:
+ * File2:
++ * File3:
+
+ 2009-12-21 Alice <alice@email.address>
+
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] New entry inserted in middle.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -11,6 +11,14 @@
+
+ Reviewed by Ray.
+
++ Changed some more code on 2009-12-21.
++
++ * File:
++
++2009-12-21 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
+ Changed some code on 2009-12-21.
+
+ * File:
+END
+ expectedReturn => {
+ hasOverlappingLines => 1,
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -11,6 +11,14 @@
+
+ Reviewed by Ray.
+
++ Changed some more code on 2009-12-21.
++
++ * File:
++
++2009-12-21 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
+ Changed some code on 2009-12-21.
+
+ * File:
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: [no change] New entry inserted earlier in the file, but after an entry with the same author and date.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -70,6 +70,14 @@
+
+ 2009-12-22 Alice <alice@email.address>
+
++ Reviewed by Sue.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
++2009-12-22 Alice <alice@email.address>
++
+ Reviewed by Ray.
+
+ Changed some code on 2009-12-22.
+END
+ expectedReturn => {
+ hasOverlappingLines => 1,
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -70,6 +70,14 @@
+
+ 2009-12-22 Alice <alice@email.address>
+
++ Reviewed by Sue.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
++2009-12-22 Alice <alice@email.address>
++
+ Reviewed by Ray.
+
+ Changed some code on 2009-12-22.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: Leading context includes first line.",
+ inputText => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,5 +1,13 @@
+ 2009-12-22 Alice <alice@email.address>
+
++ Reviewed by Sue.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
++2009-12-22 Alice <alice@email.address>
++
+ Reviewed by Ray.
+
+ Changed some code on 2009-12-22.
+END
+ expectedReturn => {
+ patch => <<'END',
+--- ChangeLog
++++ ChangeLog
+@@ -1,3 +1,11 @@
++2009-12-22 Alice <alice@email.address>
++
++ Reviewed by Sue.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: Leading context does not include first line.",
+ inputText => <<'END',
+@@ -2,6 +2,14 @@
+
+ Reviewed by Ray.
+
++ Changed some more code on 2009-12-22.
++
++ * File:
++
++2009-12-22 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
+ Changed some code on 2009-12-22.
+
+ * File:
+END
+ expectedReturn => {
+ patch => <<'END',
+@@ -1,3 +1,11 @@
++2009-12-22 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: Non-consecutive line additions.",
+
+# This can occur, for example, if the new ChangeLog entry includes
+# trailing white space in the first blank line but not the second.
+# A diff command can then match the second blank line of the new
+# ChangeLog entry with the first blank line of the old.
+# The svn diff command with the default --diff-cmd has done this.
+ inputText => <<'END',
+@@ -1,5 +1,11 @@
+ 2009-12-22 Alice <alice@email.address>
++ <pretend-whitespace>
++ Reviewed by Ray.
+
++ Changed some more code on 2009-12-22.
++
++2009-12-22 Alice <alice@email.address>
++
+ Reviewed by Ray.
+
+ Changed some code on 2009-12-22.
+END
+ expectedReturn => {
+ patch => <<'END',
+@@ -1,3 +1,9 @@
++2009-12-22 Alice <alice@email.address>
++ <pretend-whitespace>
++ Reviewed by Ray.
++
++ Changed some more code on 2009-12-22.
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+END
+ }
+},
+{ # New test
+ diffName => "fixChangeLogPatch: Additional edits after new entry.",
+ inputText => <<'END',
+@@ -2,10 +2,17 @@
+
+ Reviewed by Ray.
+
++ Changed some more code on 2009-12-22.
++
++ * File:
++
++2009-12-22 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
+ Changed some code on 2009-12-22.
+
+ * File:
+- * File2:
+
+ 2009-12-21 Alice <alice@email.address>
+
+END
+ expectedReturn => {
+ patch => <<'END',
+@@ -1,11 +1,18 @@
++2009-12-22 Alice <alice@email.address>
++
++ Reviewed by Ray.
++
++ Changed some more code on 2009-12-22.
++
++ * File:
++
+ 2009-12-22 Alice <alice@email.address>
+
+ Reviewed by Ray.
+
+ Changed some code on 2009-12-22.
+
+ * File:
+- * File2:
+
+ 2009-12-21 Alice <alice@email.address>
+
+END
+ }
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "fixChangeLogPatch(): $testCase->{diffName}: comparing";
+
+ my $got = VCSUtils::fixChangeLogPatch($testCase->{inputText});
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply($got, $expectedReturn, "$testNameStart return value.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/generatePatchCommand.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/generatePatchCommand.pl
new file mode 100644
index 0000000..483a0a8
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/generatePatchCommand.pl
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of VCSUtils::generatePatchCommand().
+
+use Test::Simple tests => 10;
+use VCSUtils;
+
+# New test
+$title = "generatePatchCommand: Undefined optional arguments.";
+
+my $argsHashRef;
+my ($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0", $title);
+ok($isForcing == 0, $title);
+
+# New test
+$title = "generatePatchCommand: Undefined options.";
+
+my $options;
+$argsHashRef = {options => $options};
+($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0", $title);
+ok($isForcing == 0, $title);
+
+# New test
+$title = "generatePatchCommand: --force and no \"ensure force\".";
+
+$argsHashRef = {options => ["--force"]};
+($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0 --force", $title);
+ok($isForcing == 1, $title);
+
+# New test
+$title = "generatePatchCommand: no --force and \"ensure force\".";
+
+$argsHashRef = {ensureForce => 1};
+($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0 --force", $title);
+ok($isForcing == 1, $title);
+
+# New test
+$title = "generatePatchCommand: \"should reverse\".";
+
+$argsHashRef = {shouldReverse => 1};
+($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0 --reverse", $title);
+
+# New test
+$title = "generatePatchCommand: --fuzz=3, --force.";
+
+$argsHashRef = {options => ["--fuzz=3", "--force"]};
+($patchCommand, $isForcing) = VCSUtils::generatePatchCommand($argsHashRef);
+
+ok($patchCommand eq "patch -p0 --force --fuzz=3", $title);
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/mergeChangeLogs.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/mergeChangeLogs.pl
new file mode 100644
index 0000000..a226e43
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/mergeChangeLogs.pl
@@ -0,0 +1,336 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2010 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of VCSUtils::mergeChangeLogs().
+
+use strict;
+
+use Test::Simple tests => 16;
+use File::Temp qw(tempfile);
+use VCSUtils;
+
+# Read contents of a file and return it.
+sub readFile($)
+{
+ my ($fileName) = @_;
+
+ local $/;
+ open(FH, "<", $fileName);
+ my $content = <FH>;
+ close(FH);
+
+ return $content;
+}
+
+# Write a temporary file and return the filename.
+sub writeTempFile($$$)
+{
+ my ($name, $extension, $content) = @_;
+
+ my ($FH, $fileName) = tempfile(
+ $name . "-XXXXXXXX",
+ DIR => ($ENV{'TMPDIR'} || "/tmp"),
+ UNLINK => 0,
+ );
+ print $FH $content;
+ close $FH;
+
+ if ($extension) {
+ my $newFileName = $fileName . $extension;
+ rename($fileName, $newFileName);
+ $fileName = $newFileName;
+ }
+
+ return $fileName;
+}
+
+# --------------------------------------------------------------------------------
+
+{
+ # New test
+ my $title = "mergeChangeLogs: traditional rejected patch success";
+
+ my $fileNewerContent = <<'EOF';
+2010-01-29 Mark Rowe <mrowe@apple.com>
+
+ Fix the Mac build.
+
+ Disable ENABLE_INDEXED_DATABASE since it is "completely non-functional".
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileNewer = writeTempFile("file", "", $fileNewerContent);
+
+ my $fileMineContent = <<'EOF';
+***************
+*** 1,3 ****
+ 2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+--- 1,9 ----
++ 2010-01-29 Oliver Hunt <oliver@apple.com>
++
++ Reviewed by Darin Adler.
++
++ JSC is failing to propagate anonymous slot count on some transitions
++
+ 2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+EOF
+ my $fileMine = writeTempFile("file", ".rej", $fileMineContent);
+ rename($fileMine, $fileNewer . ".rej");
+ $fileMine = $fileNewer . ".rej";
+
+ my $fileOlderContent = $fileNewerContent;
+ my $fileOlder = writeTempFile("file", ".orig", $fileOlderContent);
+ rename($fileOlder, $fileNewer . ".orig");
+ $fileOlder = $fileNewer . ".orig";
+
+ my $exitStatus = mergeChangeLogs($fileMine, $fileOlder, $fileNewer);
+
+ # mergeChangeLogs() should return 1 since the patch succeeded.
+ ok($exitStatus == 1, "$title: should return 1 for success");
+
+ ok(readFile($fileMine) eq $fileMineContent, "$title: \$fileMine should be unchanged");
+ ok(readFile($fileOlder) eq $fileOlderContent, "$title: \$fileOlder should be unchanged");
+
+ my $expectedContent = <<'EOF';
+2010-01-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ JSC is failing to propagate anonymous slot count on some transitions
+
+EOF
+ $expectedContent .= $fileNewerContent;
+ ok(readFile($fileNewer) eq $expectedContent, "$title: \$fileNewer should be updated to include patch");
+
+ unlink($fileMine, $fileOlder, $fileNewer);
+}
+
+# --------------------------------------------------------------------------------
+
+{
+ # New test
+ my $title = "mergeChangeLogs: traditional rejected patch failure";
+
+ my $fileNewerContent = <<'EOF';
+2010-01-29 Mark Rowe <mrowe@apple.com>
+
+ Fix the Mac build.
+
+ Disable ENABLE_INDEXED_DATABASE since it is "completely non-functional".
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileNewer = writeTempFile("file", "", $fileNewerContent);
+
+ my $fileMineContent = <<'EOF';
+***************
+*** 1,9 ****
+- 2010-01-29 Oliver Hunt <oliver@apple.com>
+-
+- Reviewed by Darin Adler.
+-
+- JSC is failing to propagate anonymous slot count on some transitions
+-
+ 2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+--- 1,3 ----
+ 2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+EOF
+ my $fileMine = writeTempFile("file", ".rej", $fileMineContent);
+ rename($fileMine, $fileNewer . ".rej");
+ $fileMine = $fileNewer . ".rej";
+
+ my $fileOlderContent = $fileNewerContent;
+ my $fileOlder = writeTempFile("file", ".orig", $fileOlderContent);
+ rename($fileOlder, $fileNewer . ".orig");
+ $fileOlder = $fileNewer . ".orig";
+
+ my $exitStatus = mergeChangeLogs($fileMine, $fileOlder, $fileNewer);
+
+ # mergeChangeLogs() should return 0 since the patch failed.
+ ok($exitStatus == 0, "$title: should return 0 for failure");
+
+ ok(readFile($fileMine) eq $fileMineContent, "$title: \$fileMine should be unchanged");
+ ok(readFile($fileOlder) eq $fileOlderContent, "$title: \$fileOlder should be unchanged");
+ ok(readFile($fileNewer) eq $fileNewerContent, "$title: \$fileNewer should be unchanged");
+
+ unlink($fileMine, $fileOlder, $fileNewer);
+}
+
+# --------------------------------------------------------------------------------
+
+{
+ # New test
+ my $title = "mergeChangeLogs: patch succeeds";
+
+ my $fileMineContent = <<'EOF';
+2010-01-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ JSC is failing to propagate anonymous slot count on some transitions
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileMine = writeTempFile("fileMine", "", $fileMineContent);
+
+ my $fileOlderContent = <<'EOF';
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileOlder = writeTempFile("fileOlder", "", $fileOlderContent);
+
+ my $fileNewerContent = <<'EOF';
+2010-01-29 Mark Rowe <mrowe@apple.com>
+
+ Fix the Mac build.
+
+ Disable ENABLE_INDEXED_DATABASE since it is "completely non-functional".
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileNewer = writeTempFile("fileNewer", "", $fileNewerContent);
+
+ my $exitStatus = mergeChangeLogs($fileMine, $fileOlder, $fileNewer);
+
+ # mergeChangeLogs() should return 1 since the patch succeeded.
+ ok($exitStatus == 1, "$title: should return 1 for success");
+
+ ok(readFile($fileMine) eq $fileMineContent, "$title: \$fileMine should be unchanged");
+ ok(readFile($fileOlder) eq $fileOlderContent, "$title: \$fileOlder should be unchanged");
+
+ my $expectedContent = <<'EOF';
+2010-01-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ JSC is failing to propagate anonymous slot count on some transitions
+
+EOF
+ $expectedContent .= $fileNewerContent;
+
+ ok(readFile($fileNewer) eq $expectedContent, "$title: \$fileNewer should be patched");
+
+ unlink($fileMine, $fileOlder, $fileNewer);
+}
+
+# --------------------------------------------------------------------------------
+
+{
+ # New test
+ my $title = "mergeChangeLogs: patch fails";
+
+ my $fileMineContent = <<'EOF';
+2010-01-29 Mark Rowe <mrowe@apple.com>
+
+ Fix the Mac build.
+
+ Disable ENABLE_INDEXED_DATABASE since it is "completely non-functional".
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileMine = writeTempFile("fileMine", "", $fileMineContent);
+
+ my $fileOlderContent = <<'EOF';
+2010-01-29 Mark Rowe <mrowe@apple.com>
+
+ Fix the Mac build.
+
+ Disable ENABLE_INDEXED_DATABASE since it is "completely non-functional".
+
+2010-01-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ JSC is failing to propagate anonymous slot count on some transitions
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileOlder = writeTempFile("fileOlder", "", $fileOlderContent);
+
+ my $fileNewerContent = <<'EOF';
+2010-01-29 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Darin Adler.
+
+ JSC is failing to propagate anonymous slot count on some transitions
+
+2010-01-29 Simon Hausmann <simon.hausmann@nokia.com>
+
+ Rubber-stamped by Maciej Stachowiak.
+
+ Fix the ARM build.
+EOF
+ my $fileNewer = writeTempFile("fileNewer", "", $fileNewerContent);
+
+ my $exitStatus = mergeChangeLogs($fileMine, $fileOlder, $fileNewer);
+
+ # mergeChangeLogs() should return a non-zero exit status since the patch failed.
+ ok($exitStatus == 0, "$title: return non-zero exit status for failure");
+
+ ok(readFile($fileMine) eq $fileMineContent, "$title: \$fileMine should be unchanged");
+ ok(readFile($fileOlder) eq $fileOlderContent, "$title: \$fileOlder should be unchanged");
+
+ # $fileNewer should still exist unchanged because the patch failed
+ ok(readFile($fileNewer) eq $fileNewerContent, "$title: \$fileNewer should be unchanged");
+
+ unlink($fileMine, $fileOlder, $fileNewer);
+}
+
+# --------------------------------------------------------------------------------
+
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl
new file mode 100644
index 0000000..9fe077f
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiff.pl
@@ -0,0 +1,1208 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseDiff().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+# The array of test cases.
+my @testCaseHashRefs = (
+{
+ # New test
+ diffName => "SVN: simple",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53052)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+
+ all:
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 53052)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+
+ all:
+END
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "53052",
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: binary file (isBinary true)",
+ inputText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: binary file (isBinary true) using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: leading junk",
+ inputText => <<'END',
+
+LEADING JUNK
+
+Index: Makefile
+===================================================================
+--- Makefile (revision 53052)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+
+ all:
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+
+LEADING JUNK
+
+Index: Makefile
+===================================================================
+--- Makefile (revision 53052)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+
+ all:
+END
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "53052",
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: copied file",
+ inputText => <<'END',
+Index: Makefile_new
+===================================================================
+--- Makefile_new (revision 53131) (from Makefile:53131)
++++ Makefile_new (working copy)
+@@ -0,0 +1,1 @@
++MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+END
+ expectedReturn => [
+[{
+ copiedFromPath => "Makefile",
+ indexPath => "Makefile_new",
+ sourceRevision => "53131",
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: two diffs",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+Index: Makefile_new
+===================================================================
+--- Makefile_new (revision 53131) (from Makefile:53131)
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+END
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "53131",
+}],
+"Index: Makefile_new\n"],
+ expectedNextLine => "===================================================================\n",
+},
+{
+ # New test
+ diffName => "SVN: SVN diff followed by Git diff", # Should not recognize Git start
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+diff --git a/Makefile b/Makefile
+index f5d5e74..3b6aa92 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,1 1,1 @@ public:
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+diff --git a/Makefile b/Makefile
+index f5d5e74..3b6aa92 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,1 1,1 @@ public:
+END
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "53131",
+}],
+undef],
+ expectedNextLine => undef,
+},
+####
+# Property Changes: Simple
+##
+{
+ # New test
+ diffName => "SVN: file change diff with property change diff",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile
+___________________________________________________________________
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+END
+ executableBitDelta => 1,
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: file change diff, followed by property change diff on different file",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile.shared
+___________________________________________________________________
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+END
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+"Property changes on: Makefile.shared\n"],
+ expectedNextLine => "___________________________________________________________________\n",
+},
+{
+ # New test
+ diffName => "SVN: property diff, followed by file change diff",
+ inputText => <<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Deleted: svn:executable
+ - *
+
+Index: Makefile.shared
+===================================================================
+--- Makefile.shared (revision 60021)
++++ Makefile.shared (working copy)
+@@ -1,3 +1,4 @@
++
+SCRIPTS_PATH ?= ../WebKitTools/Scripts
+XCODE_OPTIONS = `perl -I$(SCRIPTS_PATH) -Mwebkitdirs -e 'print XcodeOptionString()'` $(ARGS)
+END
+ expectedReturn => [
+[{
+ executableBitDelta => -1,
+ indexPath => "Makefile",
+ isSvn => 1,
+}],
+"Index: Makefile.shared\n"],
+ expectedNextLine => "===================================================================\n",
+},
+{
+ # New test
+ diffName => "SVN: property diff, followed by file change diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Deleted: svn:executable
+ - *
+
+Index: Makefile.shared
+===================================================================
+--- Makefile.shared (revision 60021)
++++ Makefile.shared (working copy)
+@@ -1,3 +1,4 @@
++
+SCRIPTS_PATH ?= ../WebKitTools/Scripts
+XCODE_OPTIONS = `perl -I$(SCRIPTS_PATH) -Mwebkitdirs -e 'print XcodeOptionString()'` $(ARGS)
+END
+),
+ expectedReturn => [
+[{
+ executableBitDelta => -1,
+ indexPath => "Makefile",
+ isSvn => 1,
+}],
+"Index: Makefile.shared\r\n"],
+ expectedNextLine => "===================================================================\r\n",
+},
+{
+ # New test
+ diffName => "SVN: copied file with property change",
+ inputText => <<'END',
+Index: NMakefile
+===================================================================
+--- NMakefile (revision 60021) (from Makefile:60021)
++++ NMakefile (working copy)
+@@ -0,0 +1,1 @@
++MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+Property changes on: NMakefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+[{
+ copiedFromPath => "Makefile",
+ executableBitDelta => 1,
+ indexPath => "NMakefile",
+ sourceRevision => "60021",
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: two consecutive property diffs",
+ inputText => <<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+
+Property changes on: Makefile.shared
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+[{
+ executableBitDelta => 1,
+ indexPath => "Makefile",
+ isSvn => 1,
+}],
+"Property changes on: Makefile.shared\n"],
+ expectedNextLine => "___________________________________________________________________\n",
+},
+{
+ # New test
+ diffName => "SVN: two consecutive property diffs using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+
+Property changes on: Makefile.shared
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+),
+ expectedReturn => [
+[{
+ executableBitDelta => 1,
+ indexPath => "Makefile",
+ isSvn => 1,
+}],
+"Property changes on: Makefile.shared\r\n"],
+ expectedNextLine => "___________________________________________________________________\r\n",
+},
+####
+# Property Changes: Binary files
+##
+{
+ # New test
+ diffName => "SVN: binary file with executable bit change",
+ inputText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+Name: svn:executable
+ + *
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ executableBitDelta => 1,
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: binary file with executable bit change usng Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+Name: svn:executable
+ + *
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ executableBitDelta => 1,
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "SVN: binary file followed by property change on different file",
+ inputText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+END
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+"Property changes on: Makefile\n"],
+ expectedNextLine => "___________________________________________________________________\n",
+},
+{
+ # New test
+ diffName => "SVN: binary file followed by property change on different file using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+END
+),
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+"Property changes on: Makefile\r\n"],
+ expectedNextLine => "___________________________________________________________________\r\n",
+},
+{
+ # New test
+ diffName => "SVN: binary file followed by file change on different file",
+ inputText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+END
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+"Index: Makefile\n"],
+ expectedNextLine => "===================================================================\n",
+},
+{
+ # New test
+ diffName => "SVN: binary file followed by file change on different file using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+
+END
+),
+ indexPath => "test_file.swf",
+ isBinary => 1,
+ isSvn => 1,
+}],
+"Index: Makefile\r\n"],
+ expectedNextLine => "===================================================================\r\n",
+},
+####
+# Property Changes: File change with property change
+##
+{
+ # New test
+ diffName => "SVN: file change diff with property change, followed by property change diff",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+
+Property changes on: Makefile.shared
+___________________________________________________________________
+Deleted: svn:executable
+ - *
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+
+
+END
+ executableBitDelta => 1,
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+"Property changes on: Makefile.shared\n"],
+ expectedNextLine => "___________________________________________________________________\n",
+},
+{
+ # New test
+ diffName => "SVN: file change diff with property change, followed by property change diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+
+Property changes on: Makefile.shared
+___________________________________________________________________
+Deleted: svn:executable
+ - *
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+
+
+END
+),
+ executableBitDelta => 1,
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+"Property changes on: Makefile.shared\r\n"],
+ expectedNextLine => "___________________________________________________________________\r\n",
+},
+{
+ # New test
+ diffName => "SVN: file change diff with property change, followed by file change diff",
+ inputText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile
+___________________________________________________________________
+Name: svn:executable
+ - *
+
+Index: Makefile.shared
+===================================================================
+--- Makefile.shared (revision 60021)
++++ Makefile.shared (working copy)
+@@ -1,3 +1,4 @@
++
+SCRIPTS_PATH ?= ../WebKitTools/Scripts
+XCODE_OPTIONS = `perl -I$(SCRIPTS_PATH) -Mwebkitdirs -e 'print XcodeOptionString()'` $(ARGS)
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+
+END
+ executableBitDelta => -1,
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+"Index: Makefile.shared\n"],
+ expectedNextLine => "===================================================================\n",
+},
+{
+ # New test
+ diffName => "SVN: file change diff with property change, followed by file change diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+Property changes on: Makefile
+___________________________________________________________________
+Name: svn:executable
+ - *
+
+Index: Makefile.shared
+===================================================================
+--- Makefile.shared (revision 60021)
++++ Makefile.shared (working copy)
+@@ -1,3 +1,4 @@
++
+SCRIPTS_PATH ?= ../WebKitTools/Scripts
+XCODE_OPTIONS = `perl -I$(SCRIPTS_PATH) -Mwebkitdirs -e 'print XcodeOptionString()'` $(ARGS)
+END
+),
+ expectedReturn => [
+[{
+ svnConvertedText => toWindowsLineEndings(<<'END', # Same as input text
+Index: Makefile
+===================================================================
+--- Makefile (revision 60021)
++++ Makefile (working copy)
+@@ -1,3 +1,4 @@
++
+ MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKit2 WebKitTools
+
+ all:
+
+
+END
+),
+ executableBitDelta => -1,
+ indexPath => "Makefile",
+ isSvn => 1,
+ sourceRevision => "60021",
+}],
+"Index: Makefile.shared\r\n"],
+ expectedNextLine => "===================================================================\r\n",
+},
+####
+# Git test cases
+##
+{
+ # New test
+ diffName => "Git: simple",
+ inputText => <<'END',
+diff --git a/Makefile b/Makefile
+index f5d5e74..3b6aa92 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,1 1,1 @@ public:
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: Makefile
+index f5d5e74..3b6aa92 100644
+--- Makefile
++++ Makefile
+@@ -1,1 1,1 @@ public:
+END
+ indexPath => "Makefile",
+ isGit => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+{ # New test
+ diffName => "Git: new file",
+ inputText => <<'END',
+diff --git a/foo.h b/foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- /dev/null
++++ b/foo.h
+@@ -0,0 +1,34 @@
++<html>
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- foo.h
++++ foo.h
+@@ -0,0 +1,34 @@
++<html>
+END
+ indexPath => "foo.h",
+ isGit => 1,
+ isNew => 1,
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "Git: file deletion",
+ inputText => <<'END',
+diff --git a/foo b/foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- a/foo
++++ /dev/null
+@@ -1,1 +0,0 @@
+-line1
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- foo
++++ foo
+@@ -1,1 +0,0 @@
+-line1
+END
+ indexPath => "foo",
+ isDeletion => 1,
+ isGit => 1,
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{
+ # New test
+ diffName => "Git: Git diff followed by SVN diff", # Should not recognize SVN start
+ inputText => <<'END',
+diff --git a/Makefile b/Makefile
+index f5d5e74..3b6aa92 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,1 1,1 @@ public:
+Index: Makefile_new
+===================================================================
+--- Makefile_new (revision 53131) (from Makefile:53131)
+END
+ expectedReturn => [
+[{
+ svnConvertedText => <<'END',
+Index: Makefile
+index f5d5e74..3b6aa92 100644
+--- Makefile
++++ Makefile
+@@ -1,1 1,1 @@ public:
+Index: Makefile_new
+===================================================================
+--- Makefile_new (revision 53131) (from Makefile:53131)
+END
+ indexPath => "Makefile",
+ isGit => 1,
+}],
+undef],
+ expectedNextLine => undef,
+},
+####
+# Git test cases: file moves (multiple return values)
+##
+{
+ diffName => "Git: rename (with similarity index 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{
+ diffName => "rename (with similarity index < 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- a/foo
++++ b/foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+},
+{
+ indexPath => "foo_new",
+ isGit => 1,
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- foo_new
++++ foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+END
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{
+ diffName => "rename (with executable bit change)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+[{
+ indexPath => "foo",
+ isDeletion => 1,
+},
+{
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+},
+{
+ executableBitDelta => 1,
+ indexPath => "foo_new",
+ isGit => 1,
+ svnConvertedText => <<'END',
+Index: foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+}],
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseDiff(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseDiff($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl
new file mode 100644
index 0000000..8c20f65
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl
@@ -0,0 +1,121 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseDiffHeader().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+# The unit tests for parseGitDiffHeader() and parseSvnDiffHeader()
+# already thoroughly test parsing each format.
+#
+# For parseDiffHeader(), it should suffice to verify that -- (1) for each
+# format, the method can return non-trivial values back for each key
+# supported by that format (e.g. "sourceRevision" for SVN), (2) the method
+# correctly sets default values when specific key-values are not set
+# (e.g. undef for "sourceRevision" for Git), and (3) key-values unique to
+# this method are set correctly (e.g. "scmFormat").
+my @testCaseHashRefs = (
+####
+# SVN test cases
+##
+{ # New test
+ diffName => "SVN: non-trivial copiedFromPath and sourceRevision values",
+ inputText => <<'END',
+Index: index_path.py
+===================================================================
+--- index_path.py (revision 53048) (from copied_from_path.py:53048)
++++ index_path.py (working copy)
+@@ -0,0 +1,7 @@
++# Python file...
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: index_path.py
+===================================================================
+--- index_path.py (revision 53048) (from copied_from_path.py:53048)
++++ index_path.py (working copy)
+END
+ copiedFromPath => "copied_from_path.py",
+ indexPath => "index_path.py",
+ isSvn => 1,
+ sourceRevision => 53048,
+},
+"@@ -0,0 +1,7 @@\n"],
+ expectedNextLine => "+# Python file...\n",
+},
+####
+# Git test cases
+##
+{ # New test case
+ diffName => "Git: Non-zero executable bit",
+ inputText => <<'END',
+diff --git a/foo.exe b/foo.exe
+old mode 100644
+new mode 100755
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.exe
+old mode 100644
+new mode 100755
+END
+ executableBitDelta => 1,
+ indexPath => "foo.exe",
+ isGit => 1,
+},
+undef],
+ expectedNextLine => undef,
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseDiffHeader(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseDiffHeader($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl
new file mode 100644
index 0000000..bc0d4d4
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseGitDiffHeader.pl
@@ -0,0 +1,494 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseGitDiffHeader().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+# The array of test cases.
+my @testCaseHashRefs = (
+{ # New test
+ diffName => "Modified file",
+ inputText => <<'END',
+diff --git a/foo.h b/foo.h
+index f5d5e74..3b6aa92 100644
+--- a/foo.h
++++ b/foo.h
+@@ -1 +1 @@
+-file contents
++new file contents
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.h
+index f5d5e74..3b6aa92 100644
+--- foo.h
++++ foo.h
+END
+ indexPath => "foo.h",
+},
+"@@ -1 +1 @@\n"],
+ expectedNextLine => "-file contents\n",
+},
+{ # New test
+ diffName => "new file",
+ inputText => <<'END',
+diff --git a/foo.h b/foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- /dev/null
++++ b/foo.h
+@@ -0,0 +1,34 @@
++<html>
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.h
+new file mode 100644
+index 0000000..3c9f114
+--- foo.h
++++ foo.h
+END
+ indexPath => "foo.h",
+ isNew => 1,
+},
+"@@ -0,0 +1,34 @@\n"],
+ expectedNextLine => "+<html>\n",
+},
+{ # New test
+ diffName => "file deletion",
+ inputText => <<'END',
+diff --git a/foo b/foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- a/foo
++++ /dev/null
+@@ -1,1 +0,0 @@
+-line1
+diff --git a/configure.ac b/configure.ac
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo
+deleted file mode 100644
+index 1e50d1d..0000000
+--- foo
++++ foo
+END
+ indexPath => "foo",
+ isDeletion => 1,
+},
+"@@ -1,1 +0,0 @@\n"],
+ expectedNextLine => "-line1\n",
+},
+{ # New test
+ diffName => "using --no-prefix",
+ inputText => <<'END',
+diff --git foo.h foo.h
+index c925780..9e65c43 100644
+--- foo.h
++++ foo.h
+@@ -1,3 +1,17 @@
++contents
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.h
+index c925780..9e65c43 100644
+--- foo.h
++++ foo.h
+END
+ indexPath => "foo.h",
+},
+"@@ -1,3 +1,17 @@\n"],
+ expectedNextLine => "+contents\n",
+},
+####
+# Copy operations
+##
+{ # New test
+ diffName => "copy (with similarity index 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 100%
+copy from foo
+copy to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 100%
+copy from foo
+copy to foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "copy (with similarity index < 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 99%
+copy from foo
+copy to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 99%
+copy from foo
+copy to foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ isCopyWithChanges => 1,
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "rename (with similarity index 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ shouldDeleteSource => 1,
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+{ # New test
+ diffName => "rename (with similarity index < 100%)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- a/foo
++++ b/foo_new
+@@ -15,3 +15,4 @@ release r deployment dep deploy:
+ line1
+ line2
+ line3
++line4
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+similarity index 99%
+rename from foo
+rename to foo_new
+index 1e50d1d..1459d21 100644
+--- foo_new
++++ foo_new
+END
+ copiedFromPath => "foo",
+ indexPath => "foo_new",
+ isCopyWithChanges => 1,
+ shouldDeleteSource => 1,
+},
+"@@ -15,3 +15,4 @@ release r deployment dep deploy:\n"],
+ expectedNextLine => " line1\n",
+},
+{ # New test
+ diffName => "rename (with executable bit change)",
+ inputText => <<'END',
+diff --git a/foo b/foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+diff --git a/bar b/bar
+index d45dd40..3494526 100644
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo_new
+old mode 100644
+new mode 100755
+similarity index 100%
+rename from foo
+rename to foo_new
+END
+ copiedFromPath => "foo",
+ executableBitDelta => 1,
+ indexPath => "foo_new",
+ isCopyWithChanges => 1,
+ shouldDeleteSource => 1,
+},
+"diff --git a/bar b/bar\n"],
+ expectedNextLine => "index d45dd40..3494526 100644\n",
+},
+####
+# Binary file test cases
+##
+{
+ # New test case
+ diffName => "New binary file",
+ inputText => <<'END',
+diff --git a/foo.gif b/foo.gif
+new file mode 100644
+index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690
+GIT binary patch
+literal 7
+OcmYex&reDa;sO8*F9L)B
+
+literal 0
+HcmV?d00001
+
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.gif
+new file mode 100644
+index 0000000000000000000000000000000000000000..64a9532e7794fcd791f6f12157406d9060151690
+GIT binary patch
+END
+ indexPath => "foo.gif",
+ isBinary => 1,
+ isNew => 1,
+},
+"literal 7\n"],
+ expectedNextLine => "OcmYex&reDa;sO8*F9L)B\n",
+},
+{
+ # New test case
+ diffName => "Deleted binary file",
+ inputText => <<'END',
+diff --git a/foo.gif b/foo.gif
+deleted file mode 100644
+index 323fae0..0000000
+GIT binary patch
+literal 0
+HcmV?d00001
+
+literal 7
+OcmYex&reDa;sO8*F9L)B
+
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.gif
+deleted file mode 100644
+index 323fae0..0000000
+GIT binary patch
+END
+ indexPath => "foo.gif",
+ isBinary => 1,
+ isDeletion => 1,
+},
+"literal 0\n"],
+ expectedNextLine => "HcmV?d00001\n",
+},
+####
+# Executable bit test cases
+##
+{
+ # New test case
+ diffName => "Modified executable file",
+ inputText => <<'END',
+diff --git a/foo b/foo
+index d03e242..435ad3a 100755
+--- a/foo
++++ b/foo
+@@ -1 +1 @@
+-file contents
++new file contents
+
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo
+index d03e242..435ad3a 100755
+--- foo
++++ foo
+END
+ indexPath => "foo",
+},
+"@@ -1 +1 @@\n"],
+ expectedNextLine => "-file contents\n",
+},
+{
+ # New test case
+ diffName => "Making file executable (last diff)",
+ inputText => <<'END',
+diff --git a/foo.exe b/foo.exe
+old mode 100644
+new mode 100755
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.exe
+old mode 100644
+new mode 100755
+END
+ executableBitDelta => 1,
+ indexPath => "foo.exe",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test case
+ diffName => "Making file executable (not last diff)",
+ inputText => <<'END',
+diff --git a/foo.exe b/foo.exe
+old mode 100644
+new mode 100755
+diff --git a/another_file.txt b/another_file.txt
+index d03e242..435ad3a 100755
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo.exe
+old mode 100644
+new mode 100755
+END
+ executableBitDelta => 1,
+ indexPath => "foo.exe",
+},
+"diff --git a/another_file.txt b/another_file.txt\n"],
+ expectedNextLine => "index d03e242..435ad3a 100755\n",
+},
+{
+ # New test case
+ diffName => "New executable file",
+ inputText => <<'END',
+diff --git a/foo b/foo
+new file mode 100755
+index 0000000..d03e242
+--- /dev/null
++++ b/foo
+@@ -0,0 +1 @@
++file contents
+
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo
+new file mode 100755
+index 0000000..d03e242
+--- foo
++++ foo
+END
+ executableBitDelta => 1,
+ indexPath => "foo",
+ isNew => 1,
+},
+"@@ -0,0 +1 @@\n"],
+ expectedNextLine => "+file contents\n",
+},
+{
+ # New test case
+ diffName => "Deleted executable file",
+ inputText => <<'END',
+diff --git a/foo b/foo
+deleted file mode 100755
+index d03e242..0000000
+--- a/foo
++++ /dev/null
+@@ -1 +0,0 @@
+-file contents
+
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: foo
+deleted file mode 100755
+index d03e242..0000000
+--- foo
++++ foo
+END
+ executableBitDelta => -1,
+ indexPath => "foo",
+ isDeletion => 1,
+},
+"@@ -1 +0,0 @@\n"],
+ expectedNextLine => "-file contents\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseGitDiffHeader(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseGitDiffHeader($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl
new file mode 100644
index 0000000..8aae3d4
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parsePatch.pl
@@ -0,0 +1,94 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseDiffHeader().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @diffHashRefKeys = ( # The hash reference keys to check per diff.
+ "copiedFromPath",
+ "indexPath",
+ "sourceRevision",
+ "svnConvertedText",
+);
+
+# New test
+my $testNameStart = "parsePatch(): [SVN: Rename] ";
+my $patch = <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+Index: Makefile_new
+===================================================================
+--- Makefile_new (revision 53131) (from Makefile:53131)
++++ Makefile_new (working copy)
+@@ -0,0 +1,1 @@
++MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+END
+
+my @expectedDiffHashRefs = (
+{
+ svnConvertedText => <<'END',
+Index: Makefile
+===================================================================
+--- Makefile (revision 53131)
++++ Makefile (working copy)
+@@ -1,1 +0,0 @@
+-MODULES = JavaScriptCore JavaScriptGlue WebCore WebKit WebKitTools
+END
+ copiedFromPath => undef,
+ indexPath => "Makefile",
+ sourceRevision => "53131",
+},
+{
+ copiedFromPath => "Makefile",
+ indexPath => "Makefile_new",
+ sourceRevision => "53131",
+},
+);
+
+plan(tests => @expectedDiffHashRefs * @diffHashRefKeys);
+
+my $fileHandle;
+open($fileHandle, "<", \$patch);
+
+my @gotDiffHashRefs = parsePatch($fileHandle);
+
+my $i = 0;
+foreach my $expectedDiffHashRef (@expectedDiffHashRefs) {
+
+ my $gotDiffHashRef = $gotDiffHashRefs[$i++];
+
+ foreach my $diffHashRefKey (@diffHashRefKeys) {
+ my $testName = "${testNameStart}[diff $i] key=\"$diffHashRefKey\"";
+ is($gotDiffHashRef->{$diffHashRefKey}, $expectedDiffHashRef->{$diffHashRefKey}, $testName);
+ }
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffFooter.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffFooter.pl
new file mode 100644
index 0000000..4f05431
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffFooter.pl
@@ -0,0 +1,397 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnDiffProperties().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+####
+# Simple test cases
+##
+{
+ # New test
+ diffName => "simple: add svn:executable",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: add svn:mergeinfo",
+ inputText => <<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Added: svn:mergeinfo
+ Merged /trunk/Makefile:r33020
+END
+ expectedReturn => [
+{
+ propertyPath => "Makefile",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:mergeinfo",
+ inputText => <<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Deleted: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+END
+ expectedReturn => [
+{
+ propertyPath => "Makefile",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: modified svn:mergeinfo",
+ inputText => <<'END',
+Property changes on: Makefile
+___________________________________________________________________
+Modified: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile:r41697
+END
+ expectedReturn => [
+{
+ propertyPath => "Makefile",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:executable",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Deleted: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => -1,
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:executable using SVN 1.4 syntax",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Name: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => -1,
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Property value followed by empty line and start of next diff
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next diff",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next property diff",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+####
+# Property value followed by empty line and start of the binary contents
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of binary contents",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "custom property followed by svn:executable, empty line and start of binary contents",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: documentation
+ + This is an example sentence.
+Added: svn:executable
+ + *
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+####
+# Successive properties
+##
+{
+ # New test
+ diffName => "svn:executable followed by custom property",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+Added: documentation
+ + This is an example sentence.
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "custom property followed by svn:executable",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: documentation
+ + This is an example sentence.
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Successive properties followed by empty line and start of next diff
+##
+{
+ # New test
+ diffName => "custom property followed by svn:executable, empty line and start of next property diff",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: documentation
+ + This is an example sentence.
+Added: svn:executable
+ + *
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "custom property followed by svn:executable, empty line and start of next index diff",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: documentation
+ + This is an example sentence.
+Added: svn:executable
+ + *
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => 1,
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+####
+# Custom properties
+##
+# FIXME: We do not support anything other than the svn:executable property.
+# We should add support for handling other properties.
+{
+ # New test
+ diffName => "simple: custom property",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Name: documentation
+ + This is an example sentence.
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "custom property followed by custom property",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: copyright
+ + Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+Added: documentation
+ + This is an example sentence.
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Malformed property diffs
+##
+# We shouldn't encounter such diffs in practice.
+{
+ # New test
+ diffName => "svn:executable followed by custom property and svn:executable",
+ inputText => <<'END',
+Property changes on: FileA
+___________________________________________________________________
+Added: svn:executable
+ + *
+Added: documentation
+ + This is an example sentence.
+Deleted: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ propertyPath => "FileA",
+ executableBitDelta => -1,
+},
+undef],
+ expectedNextLine => undef,
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnDiffProperties(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnDiffProperties($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl
new file mode 100644
index 0000000..ed8550d
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnDiffHeader.pl
@@ -0,0 +1,220 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnDiffHeader().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+# The array of test cases.
+my @testCaseHashRefs = (
+{
+ # New test
+ diffName => "simple diff",
+ inputText => <<'END',
+Index: WebKitTools/Scripts/VCSUtils.pm
+===================================================================
+--- WebKitTools/Scripts/VCSUtils.pm (revision 53004)
++++ WebKitTools/Scripts/VCSUtils.pm (working copy)
+@@ -32,6 +32,7 @@ use strict;
+ use warnings;
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: WebKitTools/Scripts/VCSUtils.pm
+===================================================================
+--- WebKitTools/Scripts/VCSUtils.pm (revision 53004)
++++ WebKitTools/Scripts/VCSUtils.pm (working copy)
+END
+ indexPath => "WebKitTools/Scripts/VCSUtils.pm",
+ sourceRevision => "53004",
+},
+"@@ -32,6 +32,7 @@ use strict;\n"],
+ expectedNextLine => " use warnings;\n",
+},
+{
+ # New test
+ diffName => "new file",
+ inputText => <<'END',
+Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl
+===================================================================
+--- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0)
++++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0)
+@@ -0,0 +1,262 @@
++#!/usr/bin/perl -w
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl
+===================================================================
+--- WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0)
++++ WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl (revision 0)
+END
+ indexPath => "WebKitTools/Scripts/webkitperl/VCSUtils_unittest/parseDiffHeader.pl",
+ isNew => 1,
+},
+"@@ -0,0 +1,262 @@\n"],
+ expectedNextLine => "+#!/usr/bin/perl -w\n",
+},
+{
+ # New test
+ diffName => "copied file",
+ inputText => <<'END',
+Index: index_path.py
+===================================================================
+--- index_path.py (revision 53048) (from copied_from_path.py:53048)
++++ index_path.py (working copy)
+@@ -0,0 +1,7 @@
++# Python file...
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: index_path.py
+===================================================================
+--- index_path.py (revision 53048) (from copied_from_path.py:53048)
++++ index_path.py (working copy)
+END
+ copiedFromPath => "copied_from_path.py",
+ indexPath => "index_path.py",
+ sourceRevision => 53048,
+},
+"@@ -0,0 +1,7 @@\n"],
+ expectedNextLine => "+# Python file...\n",
+},
+{
+ # New test
+ diffName => "contains \\r\\n lines",
+ inputText => <<END, # No single quotes to allow interpolation of "\r"
+Index: index_path.py\r
+===================================================================\r
+--- index_path.py (revision 53048)\r
++++ index_path.py (working copy)\r
+@@ -0,0 +1,7 @@\r
++# Python file...\r
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<END, # No single quotes to allow interpolation of "\r"
+Index: index_path.py\r
+===================================================================\r
+--- index_path.py (revision 53048)\r
++++ index_path.py (working copy)\r
+END
+ indexPath => "index_path.py",
+ sourceRevision => 53048,
+},
+"@@ -0,0 +1,7 @@\r\n"],
+ expectedNextLine => "+# Python file...\r\n",
+},
+{
+ # New test
+ diffName => "contains path corrections",
+ inputText => <<'END',
+Index: index_path.py
+===================================================================
+--- bad_path (revision 53048) (from copied_from_path.py:53048)
++++ bad_path (working copy)
+@@ -0,0 +1,7 @@
++# Python file...
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: index_path.py
+===================================================================
+--- index_path.py (revision 53048) (from copied_from_path.py:53048)
++++ index_path.py (working copy)
+END
+ copiedFromPath => "copied_from_path.py",
+ indexPath => "index_path.py",
+ sourceRevision => 53048,
+},
+"@@ -0,0 +1,7 @@\n"],
+ expectedNextLine => "+# Python file...\n",
+},
+####
+# Binary test cases
+##
+{
+ # New test
+ diffName => "binary file",
+ inputText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+svn:mime-type = application/octet-stream
+
+Property changes on: test_file.swf
+___________________________________________________________________
+Name: svn:mime-type
+ + application/octet-stream
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ svnConvertedText => <<'END',
+Index: test_file.swf
+===================================================================
+Cannot display: file marked as a binary type.
+END
+ indexPath => "test_file.swf",
+ isBinary => 1,
+},
+"svn:mime-type = application/octet-stream\n"],
+ expectedNextLine => "\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnDiffHeader(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnDiffHeader($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl
new file mode 100644
index 0000000..6914051
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnProperty.pl
@@ -0,0 +1,743 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnProperty().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+####
+# Simple test cases
+##
+{
+ # New test
+ diffName => "simple: add svn:executable",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:executable",
+ inputText => <<'END',
+Deleted: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => -1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: add svn:mergeinfo",
+ inputText => <<'END',
+Added: svn:mergeinfo
+ Merged /trunk/Makefile:r33020
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => 1,
+ value => "/trunk/Makefile:r33020",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:mergeinfo",
+ inputText => <<'END',
+Deleted: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => -1,
+ value => "/trunk/Makefile:r33020",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: modified svn:mergeinfo",
+ inputText => <<'END',
+Modified: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile:r41697
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => 1,
+ value => "/trunk/Makefile:r41697",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Using SVN 1.4 syntax
+##
+{
+ # New test
+ diffName => "simple: modified svn:mergeinfo using SVN 1.4 syntax",
+ inputText => <<'END',
+Name: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile:r41697
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => 1,
+ value => "/trunk/Makefile:r41697",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: delete svn:executable using SVN 1.4 syntax",
+ inputText => <<'END',
+Name: svn:executable
+ - *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => -1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "simple: add svn:executable using SVN 1.4 syntax",
+ inputText => <<'END',
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Property value followed by empty line and start of next diff
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next diff",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Added: svn:executable
+ + *
+
+Index: Makefile.shared
+END
+),
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\r\n"],
+ expectedNextLine => "Index: Makefile.shared\r\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next property diff",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of next property diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Added: svn:executable
+ + *
+
+Property changes on: Makefile.shared
+END
+),
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\r\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next diff",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Index: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Index: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Index: Makefile.shared
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\r\nlong sentence that spans\r\nmultiple lines.",
+},
+"\r\n"],
+ expectedNextLine => "Index: Makefile.shared\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next property diff",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Property changes on: Makefile.shared
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of next property diff using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Property changes on: Makefile.shared
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\r\nlong sentence that spans\r\nmultiple lines.",
+},
+"\r\n"],
+ expectedNextLine => "Property changes on: Makefile.shared\r\n",
+},
+####
+# Property value followed by empty line and start of binary patch
+##
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "add svn:executable, followed by empty line and start of binary patch using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Added: svn:executable
+ + *
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"\r\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by empty line and start of binary patch using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\r\nlong sentence that spans\r\nmultiple lines.",
+},
+"\r\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change, followed by multi-line '+' change, empty line, and start of binary patch",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "Another\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change, followed by multi-line '+' change, empty line, and start of binary patch using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "Another\r\nlong sentence that spans\r\nmultiple lines.",
+},
+"\r\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\r\n",
+},
+####
+# Successive properties
+##
+{
+ # New test
+ diffName => "single-line '+' change followed by custom property with single-line '+' change",
+ inputText => <<'END',
+Added: svn:executable
+ + *
+Added: documentation
+ + A sentence.
+END
+ expectedReturn => [
+{
+ name => "svn:executable",
+ propertyChangeDelta => 1,
+ value => "*",
+},
+"Added: documentation\n"],
+ expectedNextLine => " + A sentence.\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change, followed by svn:executable",
+ inputText => <<'END',
+Name: documentation
+ + A
+long sentence that spans
+multiple lines.
+Name: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"Name: svn:executable\n"],
+ expectedNextLine => " + *\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change, followed by multi-line '+' change and add svn:executable",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+Added: svn:executable
+ + *
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "Another\nlong sentence that spans\nmultiple lines.",
+},
+"Added: svn:executable\n"],
+ expectedNextLine => " + *\n",
+},
+{
+ # New test
+ diffName => "'Merged' change followed by 'Merged' change",
+ inputText => <<'END',
+Added: svn:mergeinfo
+ Merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile.shared:r58350
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => 1,
+ value => "/trunk/Makefile.shared:r58350",
+},
+undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Reverse-merged' change followed by 'Reverse-merged' change",
+ inputText => <<'END',
+Deleted: svn:mergeinfo
+ Reverse-merged /trunk/Makefile:r33020
+ Reverse-merged /trunk/Makefile.shared:r58350
+END
+ expectedReturn => [
+{
+ name => "svn:mergeinfo",
+ propertyChangeDelta => -1,
+ value => "/trunk/Makefile.shared:r58350",
+},
+undef],
+ expectedNextLine => undef,
+},
+####
+# Property values with trailing new lines.
+##
+# FIXME: We do not support property values with trailing new lines, since it is difficult to
+# disambiguate them from the empty line that preceeds the contents of a binary patch as
+# in the test case (above): "multi-line '+' change, followed by empty line and start of binary patch".
+{
+ # New test
+ diffName => "single-line '+' with trailing new line",
+ inputText => <<'END',
+Added: documentation
+ + A sentence.
+
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '+' with trailing new line using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Added: documentation
+ + A sentence.
+
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\r\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '+' with trailing new line, followed by empty line and start of binary patch",
+ inputText => <<'END',
+Added: documentation
+ + A sentence.
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\n"],
+ expectedNextLine => "\n",
+},
+{
+ # New test
+ diffName => "single-line '+' with trailing new line, followed by empty line and start of binary patch using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Added: documentation
+ + A sentence.
+
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => 1,
+ value => "A sentence.",
+},
+"\r\n"],
+ expectedNextLine => "\r\n",
+},
+{
+ # New test
+ diffName => "single-line '-' change with trailing new line, and single-line '+' change",
+ inputText => <<'END',
+Modified: documentation
+ - A long sentence.
+
+ + A sentence.
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A long sentence.",
+},
+"\n"],
+ expectedNextLine => " + A sentence.\n",
+},
+{
+ # New test
+ diffName => "single-line '-' change with trailing new line, and single-line '+' change using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Modified: documentation
+ - A long sentence.
+
+ + A sentence.
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A long sentence.",
+},
+"\r\n"],
+ expectedNextLine => " + A sentence.\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change with trailing new line, and multi-line '+' change",
+ inputText => <<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+
+ + Another
+long sentence that spans
+multiple lines.
+END
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A\nlong sentence that spans\nmultiple lines.",
+},
+"\n"],
+ expectedNextLine => " + Another\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change with trailing new line, and multi-line '+' change using Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+Modified: documentation
+ - A
+long sentence that spans
+multiple lines.
+
+ + Another
+long sentence that spans
+multiple lines.
+END
+),
+ expectedReturn => [
+{
+ name => "documentation",
+ propertyChangeDelta => -1, # Since we only interpret the '-' property.
+ value => "A\r\nlong sentence that spans\r\nmultiple lines.",
+},
+"\r\n"],
+ expectedNextLine => " + Another\r\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnProperty(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnProperty($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl
new file mode 100644
index 0000000..2de8ae3
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/parseSvnPropertyValue.pl
@@ -0,0 +1,233 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Research in Motion Limited 2010. All Rights Reserved.
+# Copyright (C) 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of parseSvnPropertyValue().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+{
+ # New test
+ diffName => "singe-line '+' change",
+ inputText => <<'END',
+ + *
+END
+ expectedReturn => ["*", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change",
+ inputText => <<'END',
+ - *
+END
+ expectedReturn => ["*", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Merged' change",
+ inputText => <<'END',
+ Merged /trunk/Makefile:r33020
+END
+ expectedReturn => ["/trunk/Makefile:r33020", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Reverse-merged' change",
+ inputText => <<'END',
+ Reverse-merged /trunk/Makefile:r33020
+END
+ expectedReturn => ["/trunk/Makefile:r33020", undef],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change followed by empty line with Unix line endings",
+ inputText => <<'END',
+ - *
+
+END
+ expectedReturn => ["*", "\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change followed by empty line with Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+ - *
+
+END
+),
+ expectedReturn => ["*", "\r\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "single-line '-' change followed by the next property",
+ inputText => <<'END',
+ - *
+Deleted: svn:executable
+END
+ expectedReturn => ["*", "Deleted: svn:executable\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '+' change and start of binary patch",
+ inputText => <<'END',
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", "\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\n",
+},
+{
+ # New test
+ diffName => "multi-line '+' change and start of binary patch with Windows line endings",
+ inputText => toWindowsLineEndings(<<'END',
+ + A
+long sentence that spans
+multiple lines.
+
+Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==
+END
+),
+ expectedReturn => ["A\r\nlong sentence that spans\r\nmultiple lines.", "\r\n"],
+ expectedNextLine => "Q1dTBx0AAAB42itg4GlgYJjGwMDDyODMxMDw34GBgQEAJPQDJA==\r\n",
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by '+' single-line change",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+ + A single-line.
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", " + A single-line.\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by the next property",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+Added: svn:executable
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", "Added: svn:executable\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "multi-line '-' change followed by '+' multi-line change",
+ inputText => <<'END',
+ - A
+long sentence that spans
+multiple lines.
+ + Another
+long sentence that spans
+multiple lines.
+END
+ expectedReturn => ["A\nlong sentence that spans\nmultiple lines.", " + Another\n"],
+ expectedNextLine => "long sentence that spans\n",
+},
+{
+ # New test
+ diffName => "'Reverse-merged' change followed by 'Merge' change",
+ inputText => <<'END',
+ Reverse-merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile:r41697
+END
+ expectedReturn => ["/trunk/Makefile:r33020", " Merged /trunk/Makefile:r41697\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Merged' change followed by 'Merge' change",
+ inputText => <<'END',
+ Merged /trunk/Makefile:r33020
+ Merged /trunk/Makefile.shared:r58350
+END
+ expectedReturn => ["/trunk/Makefile:r33020", " Merged /trunk/Makefile.shared:r58350\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Reverse-merged' change followed by 'Reverse-merged' change",
+ inputText => <<'END',
+ Reverse-merged /trunk/Makefile:r33020
+ Reverse-merged /trunk/Makefile.shared:r58350
+END
+ expectedReturn => ["/trunk/Makefile:r33020", " Reverse-merged /trunk/Makefile.shared:r58350\n"],
+ expectedNextLine => undef,
+},
+{
+ # New test
+ diffName => "'Reverse-merged' change followed by 'Reverse-merged' change followed by 'Merged' change",
+ inputText => <<'END',
+ Reverse-merged /trunk/Makefile:r33020
+ Reverse-merged /trunk/Makefile.shared:r58350
+ Merged /trunk/ChangeLog:r64190
+END
+ expectedReturn => ["/trunk/Makefile:r33020", " Reverse-merged /trunk/Makefile.shared:r58350\n"],
+ expectedNextLine => " Merged /trunk/ChangeLog:r64190\n",
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 2 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "parseSvnPropertyValue(): $testCase->{diffName}: comparing";
+
+ my $fileHandle;
+ open($fileHandle, "<", \$testCase->{inputText});
+ my $line = <$fileHandle>;
+
+ my @got = VCSUtils::parseSvnPropertyValue($fileHandle, $line);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is_deeply(\@got, $expectedReturn, "$testNameStart return value.");
+
+ my $gotNextLine = <$fileHandle>;
+ is($gotNextLine, $testCase->{expectedNextLine}, "$testNameStart next read line.");
+}
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl
new file mode 100644
index 0000000..a7ae807
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/prepareParsedPatch.pl
@@ -0,0 +1,136 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of prepareParsedPatch().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my $diffHashRef1 = { # not a copy, no source revision
+ copiedFromPath => undef,
+ indexPath => "indexPath1",
+ sourceRevision => undef,
+ svnConvertedText => "diff1",
+};
+my $diffHashRef2 = { # not a copy, has source revision
+ copiedFromPath => undef,
+ indexPath => "indexPath2",
+ sourceRevision => 20,
+ svnConvertedText => "diff2",
+};
+my $diffHashRef3 = { # a copy (copies always have source revision)
+ copiedFromPath => "sourcePath3",
+ indexPath => "indexPath2", # Deliberately choosing same as $diffHashRef2
+ sourceRevision => 3,
+ svnConvertedText => "diff3",
+};
+
+my @testCases = (
+{
+ # New test
+ testName => "zero diffs: empty array",
+ diffHashRefsInput => [],
+ expected => {
+ copyDiffHashRefs => [],
+ nonCopyDiffHashRefs => [],
+ sourceRevisionHash => {},
+ },
+},
+{
+ # New test
+ testName => "one diff: non-copy, no revision",
+ diffHashRefsInput => [$diffHashRef1],
+ expected => {
+ copyDiffHashRefs => [],
+ nonCopyDiffHashRefs => [$diffHashRef1],
+ sourceRevisionHash => {},
+ },
+},
+{
+ # New test
+ testName => "one diff: non-copy, has revision",
+ diffHashRefsInput => [$diffHashRef2],
+ expected => {
+ copyDiffHashRefs => [],
+ nonCopyDiffHashRefs => [$diffHashRef2],
+ sourceRevisionHash => {
+ "indexPath2" => 20,
+ }
+ },
+},
+{
+ # New test
+ testName => "one diff: copy (has revision)",
+ diffHashRefsInput => [$diffHashRef3],
+ expected => {
+ copyDiffHashRefs => [$diffHashRef3],
+ nonCopyDiffHashRefs => [],
+ sourceRevisionHash => {
+ "sourcePath3" => 3,
+ }
+ },
+},
+{
+ # New test
+ testName => "two diffs: two non-copies",
+ diffHashRefsInput => [$diffHashRef1, $diffHashRef2],
+ expected => {
+ copyDiffHashRefs => [],
+ nonCopyDiffHashRefs => [$diffHashRef1, $diffHashRef2],
+ sourceRevisionHash => {
+ "indexPath2" => 20,
+ }
+ },
+},
+{
+ # New test
+ testName => "two diffs: non-copy and copy",
+ diffHashRefsInput => [$diffHashRef2, $diffHashRef3],
+ expected => {
+ copyDiffHashRefs => [$diffHashRef3],
+ nonCopyDiffHashRefs => [$diffHashRef2],
+ sourceRevisionHash => {
+ "sourcePath3" => 3,
+ "indexPath2" => 20,
+ }
+ },
+},
+);
+
+my $testCasesCount = @testCases;
+plan(tests => $testCasesCount);
+
+foreach my $testCase (@testCases) {
+ my $testName = $testCase->{testName};
+ my @diffHashRefs = @{$testCase->{diffHashRefsInput}};
+ my $expected = $testCase->{expected};
+
+ my $got = prepareParsedPatch(0, @diffHashRefs);
+
+ is_deeply($got, $expected, $testName);
+}
+
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/removeEOL.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/removeEOL.pl
new file mode 100644
index 0000000..8bd8e90
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/removeEOL.pl
@@ -0,0 +1,56 @@
+#!/usr/bin/perl
+#
+# Copyright (C) Research In Motion Limited 2010. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Research In Motion Limited nor the names of
+# its contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of VCSUtils::removeEOL().
+
+use Test::Simple tests => 5;
+use VCSUtils;
+
+my $title;
+
+# New test
+$title = "removeEOL: Undefined argument.";
+ok(removeEOL(undef) eq "");
+
+# New test
+$title = "removeEOL: Line with Windows line ending.";
+ok(removeEOL("This line ends with a Windows line ending.\r\n") eq "This line ends with a Windows line ending.");
+
+# New test
+$title = "removeEOL: Line with Unix line ending.";
+ok(removeEOL("This line ends with a Unix line ending.\n") eq "This line ends with a Unix line ending.");
+
+# New test
+$title = "removeEOL: Line with Mac line ending.";
+ok(removeEOL("This line ends with a Mac line ending.\r") eq "This line ends with a Mac line ending.");
+
+# New test
+$title = "removeEOL: Line with a mix of line endings.";
+ok(removeEOL("This line contains a mix of line endings.\r\n\r\n\r\r\n\n\n\n") eq "This line contains a mix of line endings.");
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl
new file mode 100644
index 0000000..5acc517
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/runPatchCommand.pl
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2009, 2010 Chris Jerdonek (chris.jerdonek@gmail.com)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of VCSUtils::runPatchCommand().
+
+use Test::Simple tests => 4;
+use VCSUtils;
+
+# New test
+$title = "runPatchCommand: Unsuccessful patch, forcing.";
+
+# Since $patch has no "Index:" path, passing this to runPatchCommand
+# should not affect any files.
+my $patch = <<'END';
+Garbage patch contents
+END
+
+# We call via callSilently() to avoid output like the following to STDERR:
+# patch: **** Only garbage was found in the patch input.
+$argsHashRef = {ensureForce => 1};
+$exitStatus = callSilently(\&runPatchCommand, $patch, ".", "file_to_patch.txt", $argsHashRef);
+
+ok($exitStatus != 0, $title);
+
+# New test
+$title = "runPatchCommand: New file, --dry-run.";
+
+# This file should not exist after the tests, but we take care with the
+# file name and contents just in case.
+my $fileToPatch = "temp_OK_TO_ERASE__README_FOR_MORE.txt";
+$patch = <<END;
+Index: $fileToPatch
+===================================================================
+--- $fileToPatch (revision 0)
++++ $fileToPatch (revision 0)
+@@ -0,0 +1,5 @@
++This is a test file for WebKitTools/Scripts/VCSUtils_unittest.pl.
++This file should not have gotten created on your system.
++If it did, some unit tests don't seem to be working quite right:
++It would be great if you could file a bug report. Thanks!
++---------------------------------------------------------------------
+END
+
+# --dry-run prevents creating any files.
+# --silent suppresses the success message to STDOUT.
+$argsHashRef = {options => ["--dry-run", "--silent"]};
+$exitStatus = runPatchCommand($patch, ".", $fileToPatch, $argsHashRef);
+
+ok($exitStatus == 0, $title);
+
+# New test
+$title = "runPatchCommand: New file: \"$fileToPatch\".";
+
+$argsHashRef = {options => ["--silent"]};
+$exitStatus = runPatchCommand($patch, ".", $fileToPatch, $argsHashRef);
+
+ok($exitStatus == 0, $title);
+
+# New test
+$title = "runPatchCommand: Reverse new file (clean up previous).";
+
+$argsHashRef = {shouldReverse => 1,
+ options => ["--silent", "--remove-empty-files"]}; # To clean up.
+$exitStatus = runPatchCommand($patch, ".", $fileToPatch, $argsHashRef);
+ok($exitStatus == 0, $title);
diff --git a/Tools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl b/Tools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl
new file mode 100644
index 0000000..076d88c
--- /dev/null
+++ b/Tools/Scripts/webkitperl/VCSUtils_unittest/setChangeLogDateAndReviewer.pl
@@ -0,0 +1,128 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Unit tests of setChangeLogDateAndReviewer().
+
+use strict;
+use warnings;
+
+use Test::More;
+use VCSUtils;
+
+my @testCaseHashRefs = (
+{
+ testName => "reviewer defined and \"NOBODY (OOPS!)\" in leading junk",
+ reviewer => "John Doe",
+ epochTime => 1273414321,
+ patch => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+ expectedReturn => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-09 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by John Doe.
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+},
+{
+ testName => "reviewer not defined and \"NOBODY (OOPS!)\" in leading junk",
+ reviewer => undef,
+ epochTime => 1273414321,
+ patch => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+ expectedReturn => <<'END',
+Subject: [PATCH]
+
+Reviewed by NOBODY (OOPS!).
+
+diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
+--- a/WebCore/ChangeLog
++++ b/WebCore/ChangeLog
+@@ -1,3 +1,15 @@
++2010-05-09 Chris Jerdonek <cjerdonek@webkit.org>
++
++ Reviewed by NOBODY (OOPS!).
++
+ 2010-05-08 Chris Jerdonek <cjerdonek@webkit.org>
+
+ Reviewed by Jane Doe.
+END
+},
+);
+
+my $testCasesCount = @testCaseHashRefs;
+plan(tests => 1 * $testCasesCount); # Total number of assertions.
+
+foreach my $testCase (@testCaseHashRefs) {
+ my $testNameStart = "setChangeLogDateAndReviewer(): $testCase->{testName}: comparing";
+
+ my $patch = $testCase->{patch};
+ my $reviewer = $testCase->{reviewer};
+ my $epochTime = $testCase->{epochTime};
+
+ my $got = VCSUtils::setChangeLogDateAndReviewer($patch, $reviewer, $epochTime);
+ my $expectedReturn = $testCase->{expectedReturn};
+
+ is($got, $expectedReturn, "$testNameStart return value.");
+}