1 #!/usr/bin/perl -w 2 3 # Copyright (C) 2010, 2011 Apple Inc. All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 1. Redistributions of source code must retain the above copyright 9 # notice, this list of conditions and the following disclaimer. 10 # 2. Redistributions in binary form must reproduce the above copyright 11 # notice, this list of conditions and the following disclaimer in the 12 # documentation and/or other materials provided with the distribution. 13 # 14 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 # THE POSSIBILITY OF SUCH DAMAGE. 25 26 # Features to add: 27 # - Command line option to run a single test. 28 # - Command line option to run all tests in a suite. 29 30 use strict; 31 use warnings; 32 33 use File::Basename; 34 use FindBin; 35 use Getopt::Long qw(:config pass_through); 36 use IPC::Open3; 37 use lib $FindBin::Bin; 38 use webkitdirs; 39 use Term::ANSIColor qw(:constants); 40 41 sub dumpAllTests(); 42 sub runAllTests(); 43 sub runAllTestsInSuite($); 44 sub runTest($$); 45 sub populateTests(); 46 sub buildTestTool(); 47 48 my $showHelp = 0; 49 my $verbose = 0; 50 my $dump = 0; 51 52 my $programName = basename($0); 53 my $usage = <<EOF; 54 Usage: $programName [options] 55 --help Show this help message 56 -v|--verbose Verbose output 57 -d|--dump-tests Dump the names of testcases without running them 58 EOF 59 60 GetOptions( 61 'help' => \$showHelp, 62 'verbose|v' => \$verbose, 63 'dump|d' => \$dump, 64 ); 65 66 if ($showHelp) { 67 print STDERR $usage; 68 exit 1; 69 } 70 71 setConfiguration(); 72 buildTestTool(); 73 setPathForRunningWebKitApp(\%ENV); 74 my %testsToRun = populateTests(); 75 76 if ($dump) { 77 dumpAllTests(); 78 exit 0; 79 } 80 81 runAllTests(); 82 83 sub dumpAllTests() 84 { 85 print "Dumping test cases\n"; 86 print "------------------\n"; 87 for my $suite (keys %testsToRun) { 88 print $suite . ":\n"; 89 print map { " " . $_ . "\n" } @{ $testsToRun{$suite} }; 90 } 91 print "------------------\n"; 92 } 93 94 sub runAllTests() 95 { 96 my $anyFailures = 0; 97 for my $suite (keys %testsToRun) { 98 my $failed = runAllTestsInSuite($suite); 99 if ($failed) { 100 $anyFailures = 1; 101 } 102 } 103 return $anyFailures; 104 } 105 106 sub runAllTestsInSuite($) 107 { 108 my ($suite) = @_; 109 print "Suite: $suite\n"; 110 111 my $anyFailures = 0; 112 for my $test (@{$testsToRun{$suite}}) { 113 my $failed = runTest($suite, $test); 114 if ($failed) { 115 $anyFailures = 1; 116 } 117 } 118 119 return $anyFailures; 120 } 121 122 sub runTest($$) 123 { 124 my ($suite, $testName) = @_; 125 my $test = $suite . "/" . $testName; 126 127 print " Test: $testName -> "; 128 129 my $result = 0; 130 if (isAppleMacWebKit()) { 131 my $productDir = productDir(); 132 $ENV{DYLD_FRAMEWORK_PATH} = $productDir; 133 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; 134 my $apiTesterPath = "$productDir/TestWebKitAPI"; 135 136 local *DEVNULL; 137 my ($childIn, $childOut, $childErr); 138 unless ($verbose) { 139 open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null"; 140 $childOut = ">&DEVNULL"; 141 $childErr = ">&DEVNULL"; 142 } else { 143 $childOut = ">&STDOUT"; 144 $childErr = ">&STDERR"; 145 } 146 147 my $pid; 148 if (architecture()) { 149 $pid = open3($childIn, $childOut, $childErr, "arch", "-" . architecture(), $apiTesterPath, $test, @ARGV) or die "Failed to run test: $test."; 150 } else { 151 $pid = open3($childIn, $childOut, $childErr, $apiTesterPath, $test, @ARGV) or die "Failed to run test: $test."; 152 } 153 154 close($childIn); 155 close($childOut); 156 close($childErr); 157 close(DEVNULL) unless ($verbose); 158 159 waitpid($pid, 0); 160 $result = $?; 161 } elsif (isAppleWinWebKit()) { 162 my $apiTesterNameSuffix; 163 if (configurationForVisualStudio() ne "Debug_All") { 164 $apiTesterNameSuffix = ""; 165 } else { 166 $apiTesterNameSuffix = "_debug"; 167 } 168 my $apiTesterPath = File::Spec->catfile(productDir(), "TestWebKitAPI$apiTesterNameSuffix.exe"); 169 $result = system $apiTesterPath, $test, @ARGV; 170 } else { 171 die "run-api-tests is not supported on this platform.\n" 172 } 173 174 if ($result == 0) { 175 print BOLD GREEN, "Passed", RESET, "\n"; 176 } else { 177 print BOLD RED, "Failed", RESET, "\n"; 178 } 179 } 180 181 sub populateTests() 182 { 183 my @tests; 184 185 if (isAppleMacWebKit()) { 186 my $productDir = productDir(); 187 $ENV{DYLD_FRAMEWORK_PATH} = $productDir; 188 $ENV{WEBKIT_UNSET_DYLD_FRAMEWORK_PATH} = "YES"; 189 my $apiTesterPath = "$productDir/TestWebKitAPI"; 190 191 local *DEVNULL; 192 my ($childIn, $childOut, $childErr); 193 unless ($verbose) { 194 open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null"; 195 $childErr = ">&DEVNULL"; 196 } else { 197 $childErr = ">&STDERR"; 198 } 199 200 my $pid; 201 if (architecture()) { 202 $pid = open3($childIn, $childOut, $childErr, "arch", "-" . architecture(), $apiTesterPath, "--dump-tests") or die "Failed to build list of tests!"; 203 } else { 204 $pid = open3($childIn, $childOut, $childErr, $apiTesterPath, "--dump-tests") or die "Failed to build list of tests!"; 205 } 206 207 close($childIn); 208 @tests = <$childOut>; 209 close($childOut); 210 close($childErr); 211 close(DEVNULL) unless ($verbose); 212 213 waitpid($pid, 0); 214 my $result = $?; 215 216 if ($result) { 217 print STDERR "Failed to build list of tests!\n"; 218 exit exitStatus($result); 219 } 220 } elsif (isAppleWinWebKit()) { 221 my $apiTesterNameSuffix; 222 if (configurationForVisualStudio() ne "Debug_All") { 223 $apiTesterNameSuffix = ""; 224 } else { 225 $apiTesterNameSuffix = "_debug"; 226 } 227 my $apiTesterPath = File::Spec->catfile(productDir(), "TestWebKitAPI$apiTesterNameSuffix.exe"); 228 open(TESTS, "-|", $apiTesterPath, "--dump-tests") or die $!; 229 @tests = <TESTS>; 230 close(TESTS) or die $!; 231 } else { 232 die "run-api-tests is not supported on this platform.\n" 233 } 234 235 my %keyedTests = (); 236 for my $test (@tests) { 237 $test =~ s/[\r\n]*$//; 238 my ($suite, $testName) = split(/\//, $test); 239 push @{$keyedTests{$suite}}, $testName; 240 } 241 242 return %keyedTests; 243 } 244 245 sub buildTestTool() 246 { 247 chdirWebKit(); 248 249 my $buildTestTool = "build-api-tests"; 250 print STDERR "Running $buildTestTool\n"; 251 252 local *DEVNULL; 253 my ($childIn, $childOut, $childErr); 254 unless ($verbose) { 255 open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null"; 256 $childOut = ">&DEVNULL"; 257 $childErr = ">&DEVNULL"; 258 } else { 259 # When not quiet, let the child use our stdout/stderr. 260 $childOut = ">&STDOUT"; 261 $childErr = ">&STDERR"; 262 } 263 264 my @args = argumentsForConfiguration(); 265 my $buildProcess = open3($childIn, $childOut, $childErr, "Tools/Scripts/$buildTestTool", @args) or die "Failed to run " . $buildTestTool; 266 267 close($childIn); 268 close($childOut); 269 close($childErr); 270 close(DEVNULL) unless ($verbose); 271 272 waitpid($buildProcess, 0); 273 my $buildResult = $?; 274 275 if ($buildResult) { 276 print STDERR "Compiling TestWebKitAPI failed!\n"; 277 exit exitStatus($buildResult); 278 } 279 } 280