REGRESSION (r236481): Move soft-linking of LocalAuthentication.framework out of Local...
[WebKit-https.git] / Tools / Scripts / run-javascriptcore-tests
1 #!/usr/bin/env perl
2
3 # Copyright (C) 2005-2017 Apple 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 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 warnings;
35 use File::Spec;
36 use FindBin;
37 use Getopt::Long qw(:config pass_through);
38 use JSON::PP;
39 use lib $FindBin::Bin;
40 use List::Util qw(min max);
41 use POSIX;
42 use webkitdirs;
43
44 # determine configuration
45 setConfiguration();
46 my $configuration = configuration();
47
48 # These variables are intentionally left undefined.
49 my $root;
50 my $showHelp;
51 my @extraTests = ();
52 my $jsDriverArgs;
53 my $childProcesses;
54 my $shellRunner;
55 my $makeRunner;
56 my $rubyRunner;
57 my $testWriter;
58 my $memoryLimited;
59
60 my $buildJSC = 1;
61 my $copyJSC = 1;
62
63 use constant {
64     ENV_VAR_SAYS_DO_RUN => 4,
65     ENV_VAR_SAYS_DONT_RUN => 3,
66     RUN_IF_NO_TESTS_SPECIFIED => 2,
67     DO_RUN => 1,
68     DONT_RUN => 0,
69 };
70
71 my $runTestMasm = RUN_IF_NO_TESTS_SPECIFIED;
72 my $runTestAir = RUN_IF_NO_TESTS_SPECIFIED;
73 my $runTestB3 = RUN_IF_NO_TESTS_SPECIFIED;
74 my $runTestAPI = RUN_IF_NO_TESTS_SPECIFIED;
75 my $runJSCStress = RUN_IF_NO_TESTS_SPECIFIED;
76 my $runMozillaTests = RUN_IF_NO_TESTS_SPECIFIED;
77
78 # $runJITStressTests is special because it is not for enabling a different set of tests.
79 # Instead it is only meaningful for when we want to disable using JIT test configurations
80 # on the JSC stress test or mozilla tests.
81 my $runJITStressTests = 1;
82
83 my $runQuickMode = 0;
84
85 my $forceCollectContinuously = 0;
86 my $envVars = "";
87 my $gmallocPath = undef;
88 my $gmallocDefaultPath = "/usr/lib/libgmalloc.dylib";
89
90 my $createTarball = 0;
91 my $remoteHost = 0;
92 my $failFast = 1;
93 my %jsonData = ();
94 my $remoteConfigFile;
95 my $jsonFileName;
96 my $verbose = 0;
97
98 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTMASM}) {
99     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTMASM} eq "true") {
100         $runTestMasm = ENV_VAR_SAYS_DO_RUN;
101     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTMASM} eq "false") {
102         $runTestMasm = ENV_VAR_SAYS_DONT_RUN;
103     } else {
104         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_TESTMASM environment variable: '"
105             . $ENV{RUN_JAVASCRIPTCORE_TESTS_TESTMASM} . "'. Should be set to 'true' or 'false'.\n";
106     }
107 }
108
109 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAIR}) {
110     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAIR} eq "true") {
111         $runTestAir = ENV_VAR_SAYS_DO_RUN;
112     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAIR} eq "false") {
113         $runTestAir = ENV_VAR_SAYS_DONT_RUN;
114     } else {
115         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_TESTAIR environment variable: '"
116             . $ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAIR} . "'. Should be set to 'true' or 'false'.\n";
117     }
118 }
119
120 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTB3}) {
121     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTB3} eq "true") {
122         $runTestB3 = ENV_VAR_SAYS_DO_RUN;
123     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTB3} eq "false") {
124         $runTestB3 = ENV_VAR_SAYS_DONT_RUN;
125     } else {
126         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_TESTB3 environment variable: '"
127             . $ENV{RUN_JAVASCRIPTCORE_TESTS_TESTB3} . "'. Should be set to 'true' or 'false'.\n";
128     }
129 }
130
131 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAPI}) {
132     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAPI} eq "true") {
133         $runTestAPI = ENV_VAR_SAYS_DO_RUN;
134     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAPI} eq "false") {
135         $runTestAPI = ENV_VAR_SAYS_DONT_RUN;
136     } else {
137         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_TESTAPI environment variable: '"
138             . $ENV{RUN_JAVASCRIPTCORE_TESTS_TESTAPI} . "'. Should be set to 'true' or 'false'.\n";
139     }
140 }
141
142 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_BUILD}) {
143     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_BUILD} eq "true") {
144         $buildJSC = 1;
145     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_BUILD} eq "false") {
146         $buildJSC = 0;
147     } else {
148         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_BUILD environment variable: '"
149             . $ENV{RUN_JAVASCRIPTCORE_TESTS_BUILD} . "'. Should be set to 'true' or 'false'.\n";
150     }
151 }
152
153 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_COPY}) {
154     if ($ENV{RUN_JAVASCRIPTCORE_TESTS_COPY} eq "true") {
155         $copyJSC = 1;
156     } elsif ($ENV{RUN_JAVASCRIPTCORE_TESTS_COPY} eq "false") {
157         $copyJSC = 0;
158     } else {
159         print "Don't recognize value for RUN_JAVASCRIPTCORE_TESTS_COPY environment variable: '"
160             . $ENV{RUN_JAVASCRIPTCORE_TESTS_COPY} . "'. Should be set to 'true' or 'false'.\n";
161     }
162 }
163
164 if ($ENV{RUN_JAVASCRIPTCORE_TESTS_EXTRA_TESTS}) {
165     push @extraTests, $ENV{RUN_JAVASCRIPTCORE_TESTS_EXTRA_TESTS};
166 }
167
168 sub defaultStringForTestState {
169     my ($state) = @_;
170     if ($state == ENV_VAR_SAYS_DONT_RUN) {
171         return "will not run due to environment variable";
172     } elsif ($state == DONT_RUN) {
173         return "will not run";
174     } else {
175         return "will run";
176     }
177 }
178
179 my $programName = basename($0);
180 my $buildJSCDefault = $buildJSC ? "will check" : "will not check";
181 my $testmasmDefault = defaultStringForTestState($runTestMasm);
182 my $testairDefault = defaultStringForTestState($runTestAir);
183 my $testb3Default = defaultStringForTestState($runTestB3);
184 my $testapiDefault = defaultStringForTestState($runTestAPI);
185 my $jscStressDefault = defaultStringForTestState($runJSCStress);
186 my $mozillaTestsDefault = defaultStringForTestState($runMozillaTests);
187 my $jitStressTestsDefault = $runJITStressTests ? "will run" : " will not run";
188 my $quickModeDefault = $runQuickMode ? "some" : "all";
189 my $failFastDefault = $failFast ? "fail fast" : "don't fail fast";
190 my $copyJSCDefault = $copyJSC ? "copy" : "do not copy";
191 my $filter;
192 my $usage = <<EOF;
193 Usage: $programName [options] [options to pass to build system]
194   --help                        Show this help message
195   --root=                       Path to pre-built root containing jsc
196   --[no-]ftl-jit                Turn the FTL JIT on or off
197   --[no-]build                  Check (or don't check) to see if the jsc build is up-to-date (default: $buildJSCDefault)
198   --[no-]testmasm               Only run (or don't run) testmasm (default: $testmasmDefault)
199   --[no-]testair                Only run (or don't run) testair (default: $testairDefault)
200   --[no-]testb3                 Only run (or don't run) testb3 (default: $testb3Default)
201   --[no-]testapi                Only run (or don't run) testapi (default: $testapiDefault)
202   --[no-]jsc-stress             Only run (or don't run) the JSC stress tests (default: $jscStressDefault)
203   --[no-]mozilla-tests          Only run (or don't run) the Mozilla tests (default: $mozillaTestsDefault)
204   --[no-]jit-stress-tests       Run (or don't run) the JIT stress tests (default: $jitStressTestsDefault)
205   --[no-]quick                  Run some (or all) of the regular testing modes (default: $quickModeDefault)
206                                 If the runner only runs some it will run the default and no-cjit-validate modes.
207                                 Note, this will not change the behavior of tests that specify their own modes.
208
209   --[no-]fail-fast              Stop this script when a test family reports an error or failure (default: $failFastDefault)
210   --[no-]force-collectContinuously Enable the collectContinuously mode even if it was disabled on this platform.
211   --[no-]copy                   Copy (or don't copy) the JavaScriptCore build product before testing (default: $copyJSCDefault)
212   --json-output=                Create a file at specified path, listing failed stress tests in JSON format.
213   --tarball                     Create a tarball of the bundle produced by running the JSC stress tests.
214   --remote=                     Run the JSC stress tests on the specified remote host. Implies --tarball.
215   --remote-config-file=         Same as remote, but read config from JSON file.
216   --extra-tests=                Path to a file containing extra tests
217   --child-processes=            Specify the number of child processes.
218   --shell-runner                Uses the shell-based test runner instead of the default make-based runner.
219                                 In general the shell runner is slower than the make runner.
220   --make-runner                 Uses the faster make-based runner.
221   --ruby-runner                 Uses the ruby runner for machines without unix shell or make.
222  
223   --test-writer [writer]        Specifies the test script format."
224                                 default is to use shell scripts to run the tests"
225                                 \"ruby\" to use ruby scripts for systems without a unix shell.
226
227   --memory-limited              Indicate that we are targeting the test for a memory limited device.
228                                 Skip tests tagged with //\@skip if \$memoryLimited
229
230   --filter                      Only run tests whose name matches the given regular expression.
231   --env-vars                    Pass a list of environment variables to set before running tests.
232                                 Each environment variable should be separated by a space.
233                                 e.g. \"foo=bar x=y\" (no quotes).
234   --gmalloc:                    Run tests with Guard Malloc enabled (if no path is given: $gmallocDefaultPath is used)
235   --verbose:                    Verbose output (specify more than once to increase verbosity).
236
237 Environment Variables:
238   - set RUN_JAVASCRIPTCORE_TESTS_TESTMASM to "true" or "false" (no quotes) to determine if we run testmasm by default.
239   - set RUN_JAVASCRIPTCORE_TESTS_TESTAIR to "true" or "false" (no quotes) to determine if we run testair by default.
240   - set RUN_JAVASCRIPTCORE_TESTS_TESTB3 to "true" or "false" (no quotes) to determine if we run testb3 by default.
241   - set RUN_JAVASCRIPTCORE_TESTS_TESTAPI to "true" or "false" (no quotes) to determine if we run testapi by default.
242   - set RUN_JAVASCRIPTCORE_TESTS_BUILD to "true" or "false" (no quotes) to set the should-we-build-before-running-tests setting.
243   - set RUN_JAVASCRIPTCORE_TESTS_EXTRA_TESTS to the path of a yaml file or a directory of JS files to be run as part of run-javascriptcore-tests.
244
245 If one or more --<testname> options are specified, only those tests will run. For example,
246 the following only runs testmasm and testapi:
247     \$ run-javascriptcore-tests --testmasm --testapi
248
249 Otherwise, all tests will run unless the test is disabled using --no-<testname> or an
250 environment variable.
251 EOF
252
253 GetOptions(
254     'root=s' => \$root,
255     'extra-tests=s' => \@extraTests,
256     'build!' => \$buildJSC,
257     'testmasm!' => \$runTestMasm,
258     'testair!' => \$runTestAir,
259     'testb3!' => \$runTestB3,
260     'testapi!' => \$runTestAPI,
261     'jsc-stress!' => \$runJSCStress,
262     'mozilla-tests!' => \$runMozillaTests,
263     'jit-stress-tests!' => \$runJITStressTests,
264     'quick!' => \$runQuickMode,
265     'fail-fast!' => \$failFast,
266     'force-collectContinuously!' => \$forceCollectContinuously,
267     'copy!' => \$copyJSC,
268     'json-output=s' => \$jsonFileName,
269     'tarball!' => \$createTarball,
270     'remote=s' => \$remoteHost,
271     'remote-config-file=s' => \$remoteConfigFile,
272     'child-processes=s' => \$childProcesses,
273     'shell-runner' => \$shellRunner,
274     'make-runner' => \$makeRunner,
275     'ruby-runner' => \$rubyRunner,
276     'test-writer=s' => \$testWriter,
277     'memory-limited' => \$memoryLimited,
278     'filter=s' => \$filter,
279     'help' => \$showHelp,
280     'env-vars=s' => \$envVars,
281     'gmalloc:s' => \$gmallocPath,
282     'verbose+' => \$verbose
283 );
284
285
286 my $specificTestsSpecified = 0;
287 if ($runTestMasm == DO_RUN
288    || $runTestAir == DO_RUN
289    || $runTestB3 == DO_RUN
290    || $runTestAPI == DO_RUN
291    || $runJSCStress == DO_RUN
292    || $runMozillaTests == DO_RUN) {
293     $specificTestsSpecified = 1;
294 }
295
296 sub enableTestOrNot {
297     my ($state) = @_;
298     if ($state == RUN_IF_NO_TESTS_SPECIFIED || $state == ENV_VAR_SAYS_DO_RUN) {
299         return $specificTestsSpecified ? DONT_RUN : DO_RUN;
300     } elsif ($state == ENV_VAR_SAYS_DONT_RUN) {
301         return DONT_RUN;
302     }
303     return $state;
304 }
305
306 $runTestMasm = enableTestOrNot($runTestMasm);
307 $runTestAir = enableTestOrNot($runTestAir);
308 $runTestB3 = enableTestOrNot($runTestB3);
309 $runTestAPI = enableTestOrNot($runTestAPI);
310 $runJSCStress = enableTestOrNot($runJSCStress);
311 $runMozillaTests = enableTestOrNot($runMozillaTests);
312
313 # Assume any arguments left over from GetOptions are assumed to be build arguments
314 my @buildArgs = @ARGV;
315
316 if ($showHelp) {
317    print STDERR $usage;
318    exit 1;
319 }
320
321 setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root));
322
323 if (defined($jsonFileName)) {
324     $jsonFileName = File::Spec->rel2abs($jsonFileName);
325 }
326
327 if (!defined($root) && $buildJSC) {
328     chdirWebKit();
329
330     push(@buildArgs, argumentsForConfiguration());
331
332     print "Running: build-jsc " . join(" ", @buildArgs) . "\n";
333     my $buildResult = system "perl", File::Spec->catfile("Tools", "Scripts", "build-jsc"), @buildArgs;
334     if ($buildResult) {
335         print STDERR "Compiling jsc failed!\n";
336         exit exitStatus($buildResult);
337     }
338 }
339
340 if (defined($gmallocPath)) {
341     if ($gmallocPath eq "") {
342         $envVars .= " DYLD_INSERT_LIBRARIES=" . $gmallocDefaultPath;
343     } else {
344         $envVars .= " DYLD_INSERT_LIBRARIES=" . $gmallocPath;
345     }
346 }
347
348 my $productDir = jscProductDir();
349 $ENV{DYLD_FRAMEWORK_PATH} = $productDir;
350 $ENV{JSCTEST_timeout} = 120 unless $ENV{JSCTEST_timeout}; # Set a 120 second timeout on all jsc tests (if environment variable not defined already).
351 $ENV{TZ}="US/Pacific"; # Some tests fail if the time zone is not set to US/Pacific (<https://webkit.org/b/136363>)
352 setPathForRunningWebKitApp(\%ENV) if isCygwin();
353
354 sub testPath {
355     my ($productDir, $testName) = @_;
356     $testName .= "_debug" if configuration() eq "Debug_All";
357     return File::Spec->catfile($productDir, $testName);
358 }
359
360 sub runTest {
361     my ($testName, $jsonTestStatusName) = @_;
362
363     chdirWebKit();
364     chdir($productDir) or die "Failed to switch directory to '$productDir'\n";
365     my @command = (testPath($productDir, $testName));
366     unshift @command, ("xcrun", "-sdk", xcodeSDK(), "sim") if willUseIOSSimulatorSDK();
367     unshift @command, wrapperPrefixIfNeeded() if shouldUseJhbuild();
368
369     if ($envVars ne "") {
370         foreach my $var (split(/\s+/, $envVars)) {
371             if ($var =~ /([^=]*)=(.*)/) {
372                 $ENV{$1} = $2;
373             }
374         }
375     }
376
377     # Use an "indirect object" so that system() won't get confused if the path
378     # contains spaces (see perldoc -f exec).
379     my $testResult = system { $command[0] } @command;
380     my $exitStatus = exitStatus($testResult);
381     print "$testName completed with rc=$testResult ($exitStatus)\n\n";
382
383     if (defined($jsonFileName)) {
384         my $testStatus = ($exitStatus == 0)? JSON::PP::true: JSON::PP::false;
385         $jsonData{$jsonTestStatusName} = $testStatus;
386     }
387
388     if ($testResult && $failFast) {
389         writeJsonDataIfApplicable();
390         exit exitStatus($testResult);
391     }
392 }
393
394 if ($runTestMasm) { runTest("testmasm", "allMasmTestsPassed") }
395 if ($runTestAir) { runTest("testair", "allAirTestsPassed") }
396 if ($runTestB3) { runTest("testb3", "allB3TestsPassed") }
397 if ($runTestAPI) { runTest("testapi", "allApiTestsPassed") }
398
399
400 # Find JavaScriptCore directory
401 chdirWebKit();
402
403 runJSCStressTests();
404
405 sub runJSCStressTests
406 {
407     my $jscStressResultsDir = $productDir . "/jsc-stress-results";
408
409     my $hasTestsToRun = 0;
410     my @testList;
411     if ($runJSCStress) {
412         @testList = (
413             "PerformanceTests/SunSpider/tests/sunspider-1.0",
414             "PerformanceTests/JetStream/cdjs/cdjs-tests.yaml",
415             "PerformanceTests/ARES-6/Air/airjs-tests.yaml",
416             "PerformanceTests/ARES-6/Basic/basic-tests.yaml",
417             "JSTests/executableAllocationFuzz.yaml",
418             "JSTests/exceptionFuzz.yaml",
419             "PerformanceTests/SunSpider/no-architecture-specific-optimizations.yaml",
420             "PerformanceTests/SunSpider/shadow-chicken.yaml",
421             "PerformanceTests/SunSpider/tests/v8-v6",
422             "JSTests/stress",
423             "JSTests/microbenchmarks",
424             "JSTests/slowMicrobenchmarks.yaml",
425             "PerformanceTests/SunSpider/profiler-test.yaml",
426             "LayoutTests/jsc-layout-tests.yaml",
427             "JSTests/typeProfiler.yaml",
428             "JSTests/controlFlowProfiler.yaml",
429             "JSTests/es6.yaml",
430             "JSTests/modules.yaml",
431             "JSTests/ChakraCore.yaml",
432             "JSTests/wasm.yaml");
433         $hasTestsToRun = 1;
434     }
435
436     if ($runMozillaTests) {
437         push(@testList, "JSTests/mozilla/mozilla-tests.yaml");
438         $hasTestsToRun = 1;
439     }
440
441     # Set LANG environment variable so the stress tests will work with newer ruby (<rdar://problem/15010705>)
442     $ENV{LANG}="en_US.UTF-8";
443     my @jscStressDriverCmd = (
444         "/usr/bin/env", "ruby", "Tools/Scripts/run-jsc-stress-tests",
445         "-j", jscPath($productDir), "-o", $jscStressResultsDir);
446
447     push(@jscStressDriverCmd, @testList);
448
449     if (isWindows() && !isCygwin()) {
450         shift @jscStressDriverCmd; # Remove /usr/bin/env
451     }
452
453     if (configuration() eq "Debug") {
454         push(@jscStressDriverCmd, "--debug");
455     }
456     
457     if (!$copyJSC) {
458         push(@jscStressDriverCmd, "--no-copy");
459     }
460
461     if ($forceCollectContinuously) {
462         push(@jscStressDriverCmd, "--force-collectContinuously");
463     }
464
465     if ($envVars ne "") {
466             push(@jscStressDriverCmd, "--env-vars");
467             push(@jscStressDriverCmd, $envVars);
468     }
469
470     if ($runQuickMode) {
471         push(@jscStressDriverCmd, "--quick");
472     }
473
474     if (!$runJITStressTests) {
475         push(@jscStressDriverCmd, "--no-jit");
476     }
477     if ($createTarball) {
478         push(@jscStressDriverCmd, "--tarball");
479     }
480
481     if ($remoteHost) {
482         push(@jscStressDriverCmd, "--remote");
483         push(@jscStressDriverCmd, $remoteHost);
484     }
485
486     if ($remoteConfigFile) {
487         push(@jscStressDriverCmd, "--remote-config-file");
488         push(@jscStressDriverCmd, $remoteConfigFile);
489     }
490
491     if ($childProcesses) {
492         push(@jscStressDriverCmd, "--child-processes");
493         push(@jscStressDriverCmd, $childProcesses);
494     }
495
496     if ($shellRunner) {
497         push(@jscStressDriverCmd, "--shell-runner");
498     }
499
500     if ($makeRunner) {
501         push(@jscStressDriverCmd, "--make-runner");
502     }
503
504     if ($rubyRunner) {
505         push(@jscStressDriverCmd, "--ruby-runner");
506     }
507
508     if ($testWriter) {
509         push(@jscStressDriverCmd, "--test-writer");
510         push(@jscStressDriverCmd, $testWriter);
511     }
512
513     if ($memoryLimited) {
514         push(@jscStressDriverCmd, "--memory-limited");
515     }
516
517     if ($filter) {
518         push(@jscStressDriverCmd, "--filter");
519         push(@jscStressDriverCmd, $filter);
520     }
521
522     push(@jscStressDriverCmd, ("--verbose") x $verbose) if ($verbose > 0);
523
524     unshift @jscStressDriverCmd, wrapperPrefixIfNeeded() if shouldUseJhbuild();
525
526     # End option processing, the rest of the arguments are tests
527     push(@jscStressDriverCmd, "--");
528
529     for my $testSuite (@extraTests) {
530         push(@jscStressDriverCmd, $testSuite);
531         $hasTestsToRun = 1;
532     }
533     if (defined($ENV{"EXTRA_JSC_TESTS"})) {
534         push(@jscStressDriverCmd, $ENV{"EXTRA_JSC_TESTS"});
535         $hasTestsToRun = 1;
536     }
537
538     if (!$hasTestsToRun) {
539         exit(0);
540     }
541
542     print "Running: " . join(" ", @jscStressDriverCmd) . "\n";
543     my $result = system(@jscStressDriverCmd);
544     exit exitStatus($result) if $result;
545
546     my @jscStressFailList = readAllLines($jscStressResultsDir . "/failed");
547     @jscStressFailList = sort @jscStressFailList;
548     my $numJSCStressFailures = @jscStressFailList;
549
550     if ($numJSCStressFailures) {
551         print "\n** The following JSC stress test failures have been introduced:\n";
552         foreach my $testFailure (@jscStressFailList) {
553             print "\t$testFailure\n";
554         }
555     }
556     print "\n";
557
558     print "Results for JSC stress tests:\n";
559     printThingsFound($numJSCStressFailures, "failure", "failures", "found");
560     print "    OK.\n" if $numJSCStressFailures == 0;
561
562     print "\n";
563
564     if (defined($jsonFileName)) {
565         $jsonData{'stressTestFailures'} = \@jscStressFailList;
566     }
567
568     writeJsonDataIfApplicable();
569     exit(1) if $numJSCStressFailures;
570 }
571
572 sub readAllLines
573 {
574     my ($filename) = @_;
575     my @array = ();
576     eval {
577         open FILE, $filename or die;
578         while (<FILE>) {
579             chomp;
580             push @array, $_;
581         }
582         close FILE;
583     };
584     return @array;
585 }
586
587 sub printThingsFound
588 {
589     my ($number, $label, $pluralLabel, $verb) = @_;
590     print "    $number ";
591     if ($number == 1) {
592         print $label;
593     } else {
594         print $pluralLabel;
595     }
596     print " $verb.\n";
597 }
598
599 sub writeJsonDataIfApplicable
600 {
601     if (defined($jsonFileName)) {
602         open(my $fileHandler, ">", $jsonFileName) or die;
603         print $fileHandler "${\encode_json(\%jsonData)}\n";
604         close($fileHandler);
605     }
606 }