8b9231fee5672babf93fce9f4b847af0b0a2118f
[WebKit-https.git] / Tools / Scripts / run-javascriptcore-tests
1 #!/usr/bin/perl -w
2
3 # Copyright (C) 2005, 2013 Apple Computer, Inc.  All rights reserved.
4 # Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # 1.  Redistributions of source code must retain the above copyright
11 #     notice, this list of conditions and the following disclaimer. 
12 # 2.  Redistributions in binary form must reproduce the above copyright
13 #     notice, this list of conditions and the following disclaimer in the
14 #     documentation and/or other materials provided with the distribution. 
15 # 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 #     its contributors may be used to endorse or promote products derived
17 #     from this software without specific prior written permission. 
18 #
19 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 # Script to run the WebKit Open Source Project JavaScriptCore tests (adapted from Mozilla),
31 # as well as other tests: testapi on Mac and LayoutTests/js.
32
33 use strict;
34 use FindBin;
35 use Getopt::Long qw(:config pass_through);
36 use List::Util qw(min max);
37 use lib $FindBin::Bin;
38 use webkitdirs;
39 use POSIX;
40
41 # determine configuration
42 setConfiguration();
43 my $configuration = configuration();
44
45 my @testsToSkip = (
46     # Various ecma/Date tests sometimes fail on Windows (but not Mac) https://bugs.webkit.org/show_bug.cgi?id=25160
47     "ecma/Date/15.9.2.1.js",
48     "ecma/Date/15.9.2.2-1.js",
49     "ecma/Date/15.9.2.2-2.js",
50     "ecma/Date/15.9.2.2-3.js",
51     "ecma/Date/15.9.2.2-4.js",
52     "ecma/Date/15.9.2.2-5.js",
53     "ecma/Date/15.9.2.2-6.js",
54     # ecma_3/Date/15.9.5.7.js fails on Mac (but not Windows) https://bugs.webkit.org/show_bug.cgi?id=25161
55     "ecma_3/Date/15.9.5.6.js",
56     "ecma_3/Date/15.9.5.7.js",
57     # These three fail on Linux in certain time zones, at certain times
58     # of the year (!): https://bugs.webkit.org/show_bug.cgi?id=71371
59     "ecma/Date/15.9.5.14.js",
60     "ecma/Date/15.9.5.31-1.js",
61     "ecma/Date/15.9.5.34-1.js",
62 );
63
64 my $jsDriverArgs = "-L " . join(" ", @testsToSkip);
65 # These variables are intentionally left undefined.
66 my $root;
67 my $showHelp;
68 my $extraTests;
69
70 my $buildJSC = 1;
71
72 my $runTestAPI = isAppleMacWebKit() || isAppleWinWebKit() || isWinCairo();
73
74 my $runMozilla = 0;
75
76 # FIXME: run-jsc-stress-tests should be ported to other platforms.
77 # https://bugs.webkit.org/show_bug.cgi?id=120809
78 my $runJSCStress = !isAppleWinWebKit();
79
80 my $enableFTL = 0;
81
82 my $createTarball = 0;
83 my $remoteHost = 0;
84
85 my $programName = basename($0);
86 my $buildJSCDefault = $buildJSC ? "will check" : "will not check";
87 my $testapiDefault = $runTestAPI ? "will run" : "will not run";
88 my $mozillaDefault = $runMozilla ? "will run" : "will not run";
89 my $jscStressDefault = $runJSCStress ? "will run" : " will not run";
90 my $usage = <<EOF;
91 Usage: $programName [options] [options to pass to build system]
92   --help                        Show this help message
93   --jsDriver-args=              A string of arguments to pass to jsDriver.pl
94   --root=                       Path to pre-built root containing jsc
95   --extra-tests=                Path to a file containing extra tests
96   --[no-]ftl-jit                Turn the FTL JIT on or off
97   --[no-]build                  Check (or don't check) to see if the jsc build is up-to-date (default: $buildJSCDefault)
98   --[no-]testapi                Run (or don't run) testapi (default: $testapiDefault)
99   --[no-]jsc-stress             Run (or don't run) the JSC stress tests (default: $jscStressDefault)
100   --tarball                     Create a tarball of the bundle produced by running the JSC stress tests.
101   --remote=                     Run the JSC stress tests on the specified remote host. Implies --tarball.
102 EOF
103
104 GetOptions(
105     'j|jsDriver-args=s' => \$jsDriverArgs,
106     'root=s' => \$root,
107     'extra-tests=s' => \$extraTests,
108     'build!' => \$buildJSC,
109     'ftl-jit!' => \$enableFTL,
110     'testapi!' => \$runTestAPI,
111     'jsc-stress!' => \$runJSCStress,
112     'tarball!' => \$createTarball,
113     'remote=s' => \$remoteHost,
114     'help' => \$showHelp
115 );
116
117 # Assume any arguments left over from GetOptions are assumed to be build arguments
118 my @buildArgs = @ARGV;
119
120 # The --ftl-jit argument gets passed as a build argument.
121 if ($enableFTL) {
122     push(@buildArgs, '--ftl-jit');
123 }
124
125 # Arguments passed to --jsDriver-args (if any) are passed to jsDriver.pl
126 my @jsArgs = split(" ", $jsDriverArgs);
127
128 if ($showHelp) {
129    print STDERR $usage;
130    exit 1;
131 }
132
133 setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root));
134
135 if (!defined($root) && $buildJSC) {
136     chdirWebKit();
137
138     push(@buildArgs, argumentsForConfiguration());
139     
140     print "Running: build-jsc " . join(" ", @buildArgs) . "\n";
141     my $buildResult = system "perl", "Tools/Scripts/build-jsc", @buildArgs;
142     if ($buildResult) {
143         print STDERR "Compiling jsc failed!\n";
144         exit exitStatus($buildResult);
145     }
146 }
147
148
149 my $productDir = jscProductDir();
150 $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
151 $ENV{JSC_timeout} = 60; # Set a 60 second timeout on all jsc tests.
152 setPathForRunningWebKitApp(\%ENV) if isCygwin();
153
154 sub testapiPath($)
155 {
156     my ($productDir) = @_;
157     my $jscName = "testapi";
158     $jscName .= "_debug" if configuration() eq "Debug_All";
159     return "$productDir/$jscName";
160 }
161
162 #run api tests
163 if ($runTestAPI) {
164     chdirWebKit();
165     chdir($productDir) or die "Failed to switch directory to '$productDir'\n";
166     my @command = (testapiPath($productDir));
167     unshift @command, ("xcrun", "-sdk", xcodeSDK(), "sim") if willUseIOSSimulatorSDKWhenBuilding();
168
169     # Use an "indirect object" so that system() won't get confused if the path
170     # contains spaces (see perldoc -f exec).
171     my $testapiResult = system { $command[0] } @command;
172     exit exitStatus($testapiResult)  if $testapiResult;
173 }
174
175 # Find JavaScriptCore directory
176 chdirWebKit();
177
178 $runMozilla = !$runJSCStress;
179
180 my %mozillaFailures;
181 my %newMozillaFailures;
182
183 if ($runMozilla) {
184     chdir("Source/JavaScriptCore");
185     chdir "tests/mozilla" or die "Failed to switch directory to 'tests/mozilla'\n";
186     my @jsMozillaDriverCmd = ("perl", "jsDriver.pl", "-e", "squirrelfish", "-s", jscPath($productDir), "-f", "actual.html", @jsArgs);
187     if (isGtk() || isEfl()) {
188         my @jhbuildPrefix = sourceDir() . "/Tools/jhbuild/jhbuild-wrapper";
189     
190         if (isEfl()) {
191             push(@jhbuildPrefix, '--efl');
192         } elsif (isGtk()) {
193             push(@jhbuildPrefix, '--gtk');
194         }
195         push(@jhbuildPrefix, 'run');
196     
197         unshift(@jsMozillaDriverCmd, @jhbuildPrefix);
198     } elsif (isIOSWebKit() && willUseIOSSimulatorSDKWhenBuilding()) {
199         push @jsMozillaDriverCmd, ("--sdk", xcodeSDK());
200     }
201     print "Running: " . join(" ", @jsMozillaDriverCmd) . "\n";
202     my $result = system(@jsMozillaDriverCmd);
203     exit exitStatus($result)  if $result;
204     
205     open EXPECTED, "expected.html" or die "Failed to open 'expected.html'\n";
206     while (<EXPECTED>) {
207         last if /failures reported\.$/;
208     }
209     while (<EXPECTED>) {
210         chomp;
211         $mozillaFailures{$_} = 1;
212     }
213     close EXPECTED;
214     
215     open ACTUAL, "actual.html" or die "Failed to open 'actual.html'";
216     while (<ACTUAL>) {
217         last if /failures reported\.$/;
218     }
219     while (<ACTUAL>) {
220         chomp;
221         if ($mozillaFailures{$_}) {
222             delete $mozillaFailures{$_};
223         } else {
224             $newMozillaFailures{$_} = 1;
225         }
226     }
227     close ACTUAL;
228 }
229
230 chdirWebKit();
231 my $jscStressResultsDir = $productDir . "/jsc-stress-results";
232
233 if ($runJSCStress) {
234     # Set LANG environment variable so the stress tests will work with newer ruby (<rdar://problem/15010705>)
235     $ENV{LANG}="en_US.UTF-8";
236     my @jscStressDriverCmd = (
237         "/usr/bin/env", "ruby", "Tools/Scripts/run-jsc-stress-tests",
238         "-j", jscPath($productDir), "-o", $jscStressResultsDir,
239         "PerformanceTests/SunSpider/tests/sunspider-1.0",
240         "PerformanceTests/SunSpider/tests/v8-v6",
241         "Source/JavaScriptCore/tests/mozilla/mozilla-tests.yaml",
242         "Source/JavaScriptCore/tests/stress",
243         "LayoutTests/js/regress/script-tests",
244         "PerformanceTests/SunSpider/profiler-test.yaml",
245         "LayoutTests/jsc-layout-tests.yaml"
246     );
247     if ($enableFTL) {
248         push(@jscStressDriverCmd, "--ftl-jit");
249     }
250     if ($createTarball) {
251         push(@jscStressDriverCmd, "--tarball");
252     }
253     if ($remoteHost) {
254         push(@jscStressDriverCmd, "--remote");
255         push(@jscStressDriverCmd, $remoteHost);
256     }
257     if (defined($extraTests)) {
258         push(@jscStressDriverCmd, $extraTests);
259     }
260     if (defined($ENV{"EXTRA_JSC_TESTS"})) {
261         push(@jscStressDriverCmd, $ENV{"EXTRA_JSC_TESTS"});
262     }
263     print "Running: " . join(" ", @jscStressDriverCmd) . "\n";
264     my $result = system(@jscStressDriverCmd);
265     exit exitStatus($result) if $result;
266 }
267
268 my $numNewMozillaFailures = keys %newMozillaFailures;
269 if ($numNewMozillaFailures) {
270     print "\n** The following Mozilla test failures have been introduced:\n";
271     foreach my $mozillaFailure (sort keys %newMozillaFailures) {
272         print "\t$mozillaFailure\n";
273     }
274 }
275
276 my $numOldMozillaFailures = keys %mozillaFailures;
277 if ($numOldMozillaFailures) {
278     print "\nYou fixed the following test";
279     print "s" if $numOldMozillaFailures != 1;
280     print ":\n";
281     foreach my $mozillaFailure (sort keys %mozillaFailures) {
282         print "\t$mozillaFailure\n";
283     }
284 }
285
286 sub readAllLines
287 {
288     my ($filename) = @_;
289     my @array = ();
290     eval {
291         open FILE, $filename or die;
292         while (<FILE>) {
293             push @array, $_;
294         }
295         close FILE;
296     };
297     return @array;
298 }
299
300 sub printThingsFound
301 {
302     my ($number, $label, $pluralLabel, $verb) = @_;
303     print "    $number ";
304     if ($number == 1) {
305         print $label;
306     } else {
307         print $pluralLabel;
308     }
309     print " $verb.\n";
310 }
311
312 my @jscStressFailList = readAllLines($jscStressResultsDir . "/failed");
313 my $numJSCStressFailures = @jscStressFailList;
314
315 if ($numJSCStressFailures) {
316     print "\n** The following JSC stress test failures have been introduced:\n";
317     foreach my $testFailure (@jscStressFailList) {
318         print "\t$testFailure";
319     }
320 }
321
322 print "\n";
323
324 if ($runMozilla) {
325     print "Results for Mozilla tests:\n";
326     printThingsFound($numNewMozillaFailures, "regression", "regressions", "found");
327     printThingsFound($numOldMozillaFailures, "test", "tests", "fixed");
328     print "    OK.\n" if $numNewMozillaFailures == 0;
329     
330     print "\n";
331 }
332
333 if ($runJSCStress) {
334     print "Results for JSC stress tests:\n";
335     printThingsFound($numJSCStressFailures, "failure", "failures", "found");
336     print "    OK.\n" if $numJSCStressFailures == 0;
337     
338     print "\n";
339 }
340
341 exit(1)  if ($runMozilla && $numNewMozillaFailures) || ($runJSCStress && $numJSCStressFailures);