1dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#!/usr/bin/perl
2dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
3ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
5dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com)
6dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2007 Eric Seidel <eric@webkit.org>
7dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2009 Google Inc. All rights reserved.
8dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Copyright (C) 2009 Andras Becsi (becsi.andras@stud.u-szeged.hu), University of Szeged
9dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#
10dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Redistribution and use in source and binary forms, with or without
11dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# modification, are permitted provided that the following conditions
12dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# are met:
13dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#
14dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# 1.  Redistributions of source code must retain the above copyright
15dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#     notice, this list of conditions and the following disclaimer. 
16dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# 2.  Redistributions in binary form must reproduce the above copyright
17dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#     notice, this list of conditions and the following disclaimer in the
18dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#     documentation and/or other materials provided with the distribution. 
19dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
20dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#     its contributors may be used to endorse or promote products derived
21dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#     from this software without specific prior written permission. 
22dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#
23dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
24dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
27dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Script to run the WebKit Open Source Project layout tests.
35dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
36dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Run all the tests passed in on the command line.
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# If no tests are passed, find all the .html, .shtml, .xml, .xhtml, .xhtmlmp, .pl, .php (and svg) files in the test directory.
38dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
39dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Run each text.
40dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Compare against the existing file xxx-expected.txt.
41dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# If there is a mismatch, generate xxx-actual.txt and xxx-diffs.txt.
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
43dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# At the end, report:
44dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#   the number of tests that got the expected results
45dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#   the number of tests that ran, but did not get the expected results
46dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#   the number of tests that failed to run
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#   the number of tests that were run but had no expected results to compare against
48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
49dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse strict;
50dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse warnings;
51dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
522bde8e466a4451c7319e3a072d118917957d6554Steve Blockuse CGI;
53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochuse Config;
54dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse Cwd;
55dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse Data::Dumper;
56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
57dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Basename;
58dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Copy;
59dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Find;
60dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Path;
61dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Spec;
62dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Spec::Functions;
63dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse File::Temp;
64dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse FindBin;
65dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse Getopt::Long;
66dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse IPC::Open2;
67dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse IPC::Open3;
68dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse Time::HiRes qw(time usleep);
69dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
70dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse List::Util 'shuffle';
71dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse lib $FindBin::Bin;
73dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse webkitperl::features;
74dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse webkitperl::httpd;
75dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse webkitdirs;
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse VCSUtils;
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockuse POSIX;
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
79dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub buildPlatformResultHierarchy();
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub buildPlatformTestHierarchy(@);
8181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochsub captureSavedCrashLog($$);
82545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochsub checkPythonVersion();
83dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeCygpaths();
84dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeDumpTool();
85dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeWebSocketServer();
86dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub configureAndOpenHTTPDIfNeeded();
87dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub countAndPrintLeaks($$$);
88dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub countFinishedTest($$$$);
89dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub deleteExpectedAndActualResults($);
90dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub dumpToolDidCrash();
91dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub epiloguesAndPrologues($$);
92dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub expectedDirectoryForTest($;$;$);
93dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub fileNameWithNumber($$);
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocksub findNewestFileMatchingGlob($);
95dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub htmlForResultsSection(\@$&);
96dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub isTextOnlyTest($);
97dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub launchWithEnv(\@\%);
98dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub resolveAndMakeTestResultsDirectory();
99dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub numericcmp($$);
100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openDiffTool();
101e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blocksub buildDumpTool($);
102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openDumpTool();
103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub parseLeaksandPrintUniqueLeaks();
104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openWebSocketServerIfNeeded();
105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub pathcmp($$);
106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub printFailureMessageForTest($$);
107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub processIgnoreTests($$);
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochsub readChecksumFromPng($);
109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub readFromDumpToolWithTimer(**);
110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub readSkippedFiles($);
111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub recordActualResultsAndDiff($$);
112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub sampleDumpTool();
113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub setFileHandleNonBlocking(*$);
114f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksub setUpWindowsCrashLogSaving();
115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub slowestcmp($$);
116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub splitpath($);
117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stopRunningTestsEarlyIfNeeded();
118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stripExtension($);
119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stripMetrics($$);
12065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochsub testCrashedOrTimedOut($$$$$$);
121f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksub toCygwinPath($);
122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub toURL($);
123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub toWindowsPath($);
124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub validateSkippedArg($$;$);
125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub writeToFile($$);
126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Argument handling
128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $addPlatformExceptions = 0;
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochmy @additionalPlatformDirectories = ();
130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $complexText = 0;
131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $exitAfterNFailures = 0;
132e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkemy $exitAfterNCrashesOrTimeouts = 0;
133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $generateNewResults = isAppleMacWebKit() ? 1 : 0;
134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $guardMalloc = '';
135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# FIXME: Dynamic HTTP-port configuration in this file is wrong.  The various
136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# apache config files in LayoutTests/http/config govern the port numbers.
137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Dynamic configuration as-written will also cause random failures in
138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# an IPv6 environment.  See https://bugs.webkit.org/show_bug.cgi?id=37104.
139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $httpdPort = 8000;
140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $httpdSSLPort = 8443;
141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $ignoreMetrics = 0;
142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $webSocketPort = 8880;
143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# wss is disabled until all platforms support pyOpenSSL.
144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# my $webSocketSecurePort = 9323;
1452bde8e466a4451c7319e3a072d118917957d6554Steve Blockmy @ignoreTests;
146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $iterations = 1;
147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $launchSafari = 1;
148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $mergeDepth;
149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $pixelTests = '';
150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $platform;
151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $quiet = '';
152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $randomizeTests = 0;
153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $repeatEach = 1;
154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $report10Slowest = 0;
155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $resetResults = 0;
156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $reverseTests = 0;
157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $root;
158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $runSample = 1;
159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $shouldCheckLeaks = 0;
160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $showHelp = 0;
161f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickmy $stripEditingCallbacks;
162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $testHTTP = 1;
163545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochmy $testWebSocket = 1;
164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $testMedia = 1;
165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $tmpDir = "/tmp";
166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochmy $testResultsDirectory = File::Spec->catdir($tmpDir, "layout-test-results");
167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $testsPerDumpTool = 1000;
168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $threaded = 0;
169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# DumpRenderTree has an internal timeout of 30 seconds, so this must be > 30.
170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $timeoutSeconds = 35;
171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $tolerance = 0;
172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $treatSkipped = "default";
173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $useRemoteLinksToTests = 0;
174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $useValgrind = 0;
175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $verbose = 0;
176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $shouldWaitForHTTPD = 0;
177ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Blockmy $useWebKitTestRunner = 0;
17865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochmy $noBuildDumpTool = 0;
179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @leaksFilenames;
181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isWindows() || isMsys()) {
183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "This script has to be run under Cygwin to function correctly.\n";
184dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    exit 1;
185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Default to --no-http for wx for now.
188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$testHTTP = 0 if (isWx());
189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochmy $perlInterpreter = "perl";
191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $expectedTag = "expected";
1932bde8e466a4451c7319e3a072d118917957d6554Steve Blockmy $mismatchTag = "mismatch";
194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $actualTag = "actual";
195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $prettyDiffTag = "pretty-diff";
196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $diffsTag = "diffs";
197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $errorTag = "stderr";
1982fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockmy $crashLogTag = "crash-log";
1992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2002fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockmy $windowsCrashLogFilePrefix = "CrashLog";
201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
202f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick# These are defined here instead of closer to where they are used so that they
203f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick# will always be accessible from the END block that uses them, even if the user
204f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick# presses Ctrl-C before Perl has finished evaluating this whole file.
205f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickmy $windowsPostMortemDebuggerKey = "/HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/AeDebug";
206f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickmy %previousWindowsPostMortemDebuggerValues;
207f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
208e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkemy $realPlatform;
209e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @macPlatforms = ("mac-tiger", "mac-leopard", "mac-snowleopard", "mac");
211e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkemy @winPlatforms = ("win-xp", "win-vista", "win-7", "win");
212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isAppleMacWebKit()) {
214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isTiger()) {
215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "mac-tiger";
216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $tolerance = 1.0;
217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isLeopard()) {
218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "mac-leopard";
219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $tolerance = 0.1;
220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isSnowLeopard()) {
221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "mac-snowleopard";
222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $tolerance = 0.1;
223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "mac";
225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
226dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isQt()) {
227dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isDarwin()) {
228dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "qt-mac";
229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isLinux()) {
230dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "qt-linux";
231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isWindows() || isCygwin()) {
232dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "qt-win";
233dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $platform = "qt";
235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
236dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isGtk()) {
237dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $platform = "gtk";
238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isWx()) {
239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $platform = "wx";
240a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} elsif (isCygwin() || isWindows()) {
241e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (isWindowsXP()) {
242e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $platform = "win-xp";
243e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    } elsif (isWindowsVista()) {
244e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $platform = "win-vista";
245e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    } elsif (isWindows7()) {
246e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $platform = "win-7";
247e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    } else {
248e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $platform = "win";
249e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
250dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
251dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
252a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochif (isQt() || isAppleWinWebKit()) {
2530617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    my $testfontPath = $ENV{"WEBKIT_TESTFONTS"};
2540617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    if (!$testfontPath || !-d "$testfontPath") {
2550617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        print "The WEBKIT_TESTFONTS environment variable is not defined or not set properly\n";
2560617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        print "You must set it before running the tests.\n";
2570617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        print "Use git to grab the actual fonts from http://gitorious.org/qtwebkit/testfonts\n";
2580617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        exit 1;
2590617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    }
2600617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen}
2610617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen
262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!defined($platform)) {
263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "WARNING: Your platform is not recognized. Any platform-specific results will be generated in platform/undefined.\n";
264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $platform = "undefined";
265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
266dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
267545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochif (!checkPythonVersion()) {
268545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    print "WARNING: Your platform does not have Python 2.5+, which is required to run websocket server, so disabling websocket/tests.\n";
269545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    $testWebSocket = 0;
270545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
271545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $programName = basename($0);
273dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $launchSafariDefault = $launchSafari ? "launch" : "do not launch";
274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $httpDefault = $testHTTP ? "run" : "do not run";
275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $sampleDefault = $runSample ? "run" : "do not run";
276dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $usage = <<EOF;
278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockUsage: $programName [options] [testdir|testpath ...]
279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --add-platform-exceptions       Put new results for non-platform-specific failing tests into the platform-specific results directory
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch  --additional-platform-directory path/to/directory
2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                                  Look in the specified directory before looking in any of the default platform-specific directories
282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --complex-text                  Use the complex text code path for all text (Mac OS X and Windows only)
283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -c|--configuration config       Set DumpRenderTree build configuration
284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -g|--guard-malloc               Enable malloc guard
285e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke  --exit-after-n-failures N       Exit after the first N failures (includes crashes) instead of running all tests
286e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke  --exit-after-n-crashes-or-timeouts N
287e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke                                  Exit after the first N crashes instead of running all tests
288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -h|--help                       Show this help message
289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]http                     Run (or do not run) http tests (default: $httpDefault)
290dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]wait-for-httpd           Wait for httpd if some other test session is using it already (same as WEBKIT_WAIT_FOR_HTTPD=1). (default: $shouldWaitForHTTPD) 
291dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -i|--ignore-tests               Comma-separated list of directories or tests to ignore
292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --iterations n                  Number of times to run the set of tests (e.g. ABCABCABC)
293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]launch-safari            Launch (or do not launch) Safari to display test results (default: $launchSafariDefault)
294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -l|--leaks                      Enable leaks checking
295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]new-test-results         Generate results for new tests
296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --nthly n                       Restart DumpRenderTree every n tests (default: $testsPerDumpTool)
297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -p|--pixel-tests                Enable pixel tests
298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --tolerance t                   Ignore image differences less than this percentage (default: $tolerance)
299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --platform                      Override the detected platform to use for tests and results (default: $platform)
300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --port                          Web server port to use with http tests
301dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -q|--quiet                      Less verbose output
302dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --reset-results                 Reset ALL results (including pixel tests if --pixel-tests is set)
303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -o|--results-directory          Output results directory (default: $testResultsDirectory)
304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --random                        Run the tests in a random order
305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --repeat-each n                 Number of times to run each test (e.g. AAABBBCCC)
306dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --reverse                       Run the tests in reverse alphabetical order
307dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --root                          Path to root tools build
308dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]sample-on-timeout        Run sample on timeout (default: $sampleDefault) (Mac OS X only)
309dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -1|--singly                     Isolate each test case run (implies --nthly 1 --verbose)
310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --skipped=[default|ignore|only] Specifies how to treat the Skipped file
311dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                     default: Tests/directories listed in the Skipped file are not tested
312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                     ignore:  The Skipped file is ignored
313dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                     only:    Only those tests/directories listed in the Skipped file will be run
314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --slowest                       Report the 10 slowest tests
315dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --ignore-metrics                Ignore metrics in tests
316dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --[no-]strip-editing-callbacks  Remove editing callbacks from expected results
317dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -t|--threaded                   Run a concurrent JavaScript thead with each test
318dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --timeout t                     Sets the number of seconds before a test times out (default: $timeoutSeconds)
319dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --valgrind                      Run DumpRenderTree inside valgrind (Qt/Linux only)
320dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -v|--verbose                    More verbose output (overrides --quiet)
321dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  -m|--merge-leak-depth arg       Merges leak callStacks and prints the number of unique leaks beneath a callstack depth of arg.  Defaults to 5.
322dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  --use-remote-links-to-tests     Link to test files within the SVN repository in the results.
323db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block  -2|--webkit-test-runner         Use WebKitTestRunner rather than DumpRenderTree.
324dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockEOF
325dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
326dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlocksetConfiguration();
327dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $getOptionsResult = GetOptions(
329dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'add-platform-exceptions' => \$addPlatformExceptions,
3302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    'additional-platform-directory=s' => \@additionalPlatformDirectories,
331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'complex-text' => \$complexText,
332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'exit-after-n-failures=i' => \$exitAfterNFailures,
333e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    'exit-after-n-crashes-or-timeouts=i' => \$exitAfterNCrashesOrTimeouts,
334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'guard-malloc|g' => \$guardMalloc,
335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'help|h' => \$showHelp,
336dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'http!' => \$testHTTP,
337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'wait-for-httpd!' => \$shouldWaitForHTTPD,
338dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'ignore-metrics!' => \$ignoreMetrics,
3392bde8e466a4451c7319e3a072d118917957d6554Steve Block    'ignore-tests|i=s' => \@ignoreTests,
340dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'iterations=i' => \$iterations,
341dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'launch-safari!' => \$launchSafari,
342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'leaks|l' => \$shouldCheckLeaks,
343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'merge-leak-depth|m:5' => \$mergeDepth,
344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'new-test-results!' => \$generateNewResults,
34565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    'no-build' => \$noBuildDumpTool,
346dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'nthly=i' => \$testsPerDumpTool,
347dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'pixel-tests|p' => \$pixelTests,
348dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'platform=s' => \$platform,
349dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'port=i' => \$httpdPort,
350dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'quiet|q' => \$quiet,
351dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'random' => \$randomizeTests,
352dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'repeat-each=i' => \$repeatEach,
353dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'reset-results' => \$resetResults,
354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'results-directory|o=s' => \$testResultsDirectory,
355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'reverse' => \$reverseTests,
356dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'root=s' => \$root,
357dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'sample-on-timeout!' => \$runSample,
358dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'singly|1' => sub { $testsPerDumpTool = 1; },
359dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'skipped=s' => \&validateSkippedArg,
360dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'slowest' => \$report10Slowest,
361dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'strip-editing-callbacks!' => \$stripEditingCallbacks,
362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'threaded|t' => \$threaded,
363dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'timeout=i' => \$timeoutSeconds,
364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'tolerance=f' => \$tolerance,
365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'use-remote-links-to-tests' => \$useRemoteLinksToTests,
366dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'valgrind' => \$useValgrind,
367dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    'verbose|v' => \$verbose,
368db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    'webkit-test-runner|2' => \$useWebKitTestRunner,
369dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block);
370dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
371dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$getOptionsResult || $showHelp) {
372dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print STDERR $usage;
373dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    exit 1;
374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
375dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
376e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkeif ($useWebKitTestRunner) {
377e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (isAppleMacWebKit()) {
378e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $realPlatform = $platform;
379e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $platform = "mac-wk2";
380db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    } elsif (isAppleWinWebKit()) {
381f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        $stripEditingCallbacks = 0 unless defined $stripEditingCallbacks;
382db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        $realPlatform = $platform;
383db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        $platform = "win-wk2";
384a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    } elsif (isQt()) {
385a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        $realPlatform = $platform;
386a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        $platform = "qt-wk2";
387e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
388e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
389e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
39028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu$timeoutSeconds *= 10 if $guardMalloc;
39128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
392f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick$stripEditingCallbacks = isCygwin() unless defined $stripEditingCallbacks;
393e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
394dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $ignoreSkipped = $treatSkipped eq "ignore";
395dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $skippedOnly = $treatSkipped eq "only";
396dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $configuration = configuration();
398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# We need an environment variable to be able to enable the feature per-slave
400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$shouldWaitForHTTPD = $ENV{"WEBKIT_WAIT_FOR_HTTPD"} unless ($shouldWaitForHTTPD);
401dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$verbose = 1 if $testsPerDumpTool == 1;
402dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($shouldCheckLeaks && $testsPerDumpTool > 1000) {
404dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print STDERR "\nWARNING: Running more than 1000 tests at a time with MallocStackLogging enabled may cause a crash.\n\n";
405dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
406dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
407dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Stack logging does not play well with QuickTime on Tiger (rdar://problem/5537157)
408dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$testMedia = 0 if $shouldCheckLeaks && isTiger();
409dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Generating remote links causes a lot of unnecessary spew on GTK build bot
411dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$useRemoteLinksToTests = 0 if isGtk();
412dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
413dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlocksetConfigurationProductDir(Cwd::abs_path($root)) if (defined($root));
414dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $productDir = productDir();
415dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$productDir .= "/bin" if isQt();
416dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$productDir .= "/Programs" if isGtk();
417dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
418dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockchdirWebKit();
419dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
42065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochif (!defined($root) && !$noBuildDumpTool) {
421e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    # FIXME: We build both DumpRenderTree and WebKitTestRunner for
422e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    # WebKitTestRunner runs becuase DumpRenderTree still includes
423e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    # the DumpRenderTreeSupport module and the TestNetscapePlugin.
424e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    # These two projects should be factored out into their own
425e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    # projects.
426e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    buildDumpTool("DumpRenderTree");
427e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    buildDumpTool("WebKitTestRunner") if $useWebKitTestRunner;
428dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
429dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
430e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockmy $dumpToolName = $useWebKitTestRunner ? "WebKitTestRunner" : "DumpRenderTree";
431e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
432a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochif (isAppleWinWebKit()) {
4334576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    $dumpToolName .= "_debug" if configurationForVisualStudio() eq "Debug_All";
4342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    $dumpToolName .= "_debug" if configurationForVisualStudio() eq "Debug_Cairo_CFLite";
435a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    $dumpToolName .= $Config{_exe};
436a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
437a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochmy $dumpTool = File::Spec->catfile($productDir, $dumpToolName);
438dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdie "can't find executable $dumpToolName (looked in $productDir)\n" unless -x $dumpTool;
439dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
440dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $imageDiffTool = "$productDir/ImageDiff";
4414576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang$imageDiffTool .= "_debug" if isCygwin() && configurationForVisualStudio() eq "Debug_All";
4422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch$imageDiffTool .= "_debug" if isCygwin() && configurationForVisualStudio() eq "Debug_Cairo_CFLite";
443dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdie "can't find executable $imageDiffTool (looked in $productDir)\n" if $pixelTests && !-x $imageDiffTool;
444dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
445dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockcheckFrameworks() unless isCygwin();
446dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
447dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isAppleMacWebKit()) {
448dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @INC, $productDir;
449dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    require DumpRenderTreeSupport;
450dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
451dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
452dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $layoutTestsName = "LayoutTests";
453dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $testDirectory = File::Spec->rel2abs($layoutTestsName);
454dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $expectedDirectory = $testDirectory;
455dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $platformBaseDirectory = catdir($testDirectory, "platform");
456dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $platformTestDirectory = catdir($platformBaseDirectory, $platform);
457dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @platformResultHierarchy = buildPlatformResultHierarchy();
458dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @platformTestHierarchy = buildPlatformTestHierarchy(@platformResultHierarchy);
459dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
460dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$expectedDirectory = $ENV{"WebKitExpectedTestResultsDirectory"} if $ENV{"WebKitExpectedTestResultsDirectory"};
461dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
462dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$testResultsDirectory = File::Spec->rel2abs($testResultsDirectory);
46365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch# $testResultsDirectory must be empty before testing.
46465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochrmtree $testResultsDirectory;
465dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $testResults = File::Spec->catfile($testResultsDirectory, "results.html");
466dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
467dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isAppleMacWebKit()) {
468dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print STDERR "Compiling Java tests\n";
469dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $javaTestsDirectory = catdir($testDirectory, "java");
470dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
471dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (system("/usr/bin/make", "-C", "$javaTestsDirectory")) {
472dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        exit 1;
473dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
47481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch} elsif (isCygwin()) {
47581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    setUpWindowsCrashLogSaving();
476dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
477dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
478dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint "Running tests from $testDirectory\n";
479dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($pixelTests) {
480dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "Enabling pixel tests with a tolerance of $tolerance%\n";
481dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isDarwin()) {
48281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (!$useWebKitTestRunner) {
48381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            print "WARNING: Temporarily changing the main display color profile:\n";
48481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            print "\tThe colors on your screen will change for the duration of the testing.\n";
48581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            print "\tThis allows the pixel tests to have consistent color values across all machines.\n";
48681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
48781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
488dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (isPerianInstalled()) {
489dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "WARNING: Perian's QuickTime component is installed and this may affect pixel test results!\n";
490dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "\tYou should avoid generating new pixel results in this environment.\n";
491dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "\tSee https://bugs.webkit.org/show_bug.cgi?id=22615 for details.\n";
492dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
493dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
495dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
496dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksystem "ln", "-s", $testDirectory, "/tmp/LayoutTests" unless -x "/tmp/LayoutTests";
497dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
498dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %ignoredFiles = ( "results.html" => 1 );
499dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %ignoredDirectories = map { $_ => 1 } qw(platform);
500dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %ignoredLocalDirectories = map { $_ => 1 } qw(.svn _svn resources script-tests);
501dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %supportedFileExtensions = map { $_ => 1 } qw(html shtml xml xhtml xhtmlmp pl php);
502dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
503dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!checkWebCoreFeatureSupport("MathML", 0)) {
504dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'mathml'} = 1;
505dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
506dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
507dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# FIXME: We should fix webkitperl/features.pm:hasFeature() to do the correct feature detection for Cygwin.
508dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (checkWebCoreFeatureSupport("SVG", 0)) {
509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $supportedFileExtensions{'svg'} = 1;
510dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isCygwin()) {
511dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $supportedFileExtensions{'svg'} = 1;
512dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} else {
513dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredLocalDirectories{'svg'} = 1;
514dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
515dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
516dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$testHTTP) {
517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'http'} = 1;
518dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'websocket'} = 1;
519dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
520545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochif (!$testWebSocket) {
521545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    $ignoredDirectories{'websocket'} = 1;
522545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
524dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$testMedia) {
525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'media'} = 1;
526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'http/tests/media'} = 1;
527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
528dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
529dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $supportedFeaturesResult = "";
530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isCygwin()) {
532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Collect supported features list
533dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    setPathForRunningWebKitApp(\%ENV);
534a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    my $supportedFeaturesCommand = "\"$dumpTool\" --print-supported-features 2>&1";
535dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $supportedFeaturesResult = `$supportedFeaturesCommand 2>&1`;
536dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
537dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
538dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $hasAcceleratedCompositing = 0;
539dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $has3DRendering = 0;
540dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
541dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isCygwin()) {
542dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $hasAcceleratedCompositing = $supportedFeaturesResult =~ /AcceleratedCompositing/;
543dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $has3DRendering = $supportedFeaturesResult =~ /3DRendering/;
544dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} else {
545dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $hasAcceleratedCompositing = checkWebCoreFeatureSupport("Accelerated Compositing", 0);
546dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $has3DRendering = checkWebCoreFeatureSupport("3D Rendering", 0);
547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
548dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
549dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$hasAcceleratedCompositing) {
550dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'compositing'} = 1;
551e14391e94c850b8bd03680c23b38978db68687a8John Reck
552e14391e94c850b8bd03680c23b38978db68687a8John Reck    # This test has slightly different floating-point rounding when accelerated
553e14391e94c850b8bd03680c23b38978db68687a8John Reck    # compositing is enabled.
554e14391e94c850b8bd03680c23b38978db68687a8John Reck    $ignoredFiles{'svg/custom/use-on-symbol-inside-pattern.svg'} = 1;
555e14391e94c850b8bd03680c23b38978db68687a8John Reck
5562bde8e466a4451c7319e3a072d118917957d6554Steve Block    # This test has an iframe that is put in a layer only in compositing mode.
5572bde8e466a4451c7319e3a072d118917957d6554Steve Block    $ignoredFiles{'media/media-document-audio-repaint.html'} = 1;
5582bde8e466a4451c7319e3a072d118917957d6554Steve Block
559e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (isAppleWebKit()) {
560e14391e94c850b8bd03680c23b38978db68687a8John Reck        # In Apple's ports, the default controls for <video> contain a "full
561e14391e94c850b8bd03680c23b38978db68687a8John Reck        # screen" button only if accelerated compositing is enabled.
562e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/controls-after-reload.html'} = 1;
563e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/controls-drag-timebar.html'} = 1;
564e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/controls-strict.html'} = 1;
565e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/controls-styling.html'} = 1;
5662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        $ignoredFiles{'media/controls-without-preload.html'} = 1;
567e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/video-controls-rendering.html'} = 1;
568e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/video-display-toggle.html'} = 1;
569e14391e94c850b8bd03680c23b38978db68687a8John Reck        $ignoredFiles{'media/video-no-audio.html'} = 1;
570e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
571e14391e94c850b8bd03680c23b38978db68687a8John Reck
572e14391e94c850b8bd03680c23b38978db68687a8John Reck    # Here we're using !$hasAcceleratedCompositing as a proxy for "is a headless XP machine" (like
573e14391e94c850b8bd03680c23b38978db68687a8John Reck    # our test slaves). Headless XP machines can neither support accelerated compositing nor pass
574e14391e94c850b8bd03680c23b38978db68687a8John Reck    # this test, so skipping the test here is expedient, if a little sloppy. See
575e14391e94c850b8bd03680c23b38978db68687a8John Reck    # <http://webkit.org/b/48333>.
576e14391e94c850b8bd03680c23b38978db68687a8John Reck    $ignoredFiles{'platform/win/plugins/npn-invalidate-rect-invalidates-window.html'} = 1 if isAppleWinWebKit();
577dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
578dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
579dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$has3DRendering) {
580dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'animations/3d'} = 1;
581dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'transforms/3d'} = 1;
582e14391e94c850b8bd03680c23b38978db68687a8John Reck
583e14391e94c850b8bd03680c23b38978db68687a8John Reck    # These tests use the -webkit-transform-3d media query.
584e14391e94c850b8bd03680c23b38978db68687a8John Reck    $ignoredFiles{'fast/media/mq-transform-02.html'} = 1;
585e14391e94c850b8bd03680c23b38978db68687a8John Reck    $ignoredFiles{'fast/media/mq-transform-03.html'} = 1;
586dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
587dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
588dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!checkWebCoreFeatureSupport("3D Canvas", 0)) {
589dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'fast/canvas/webgl'} = 1;
590967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    $ignoredDirectories{'compositing/webgl'} = 1;
591bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    $ignoredDirectories{'http/tests/canvas/webgl'} = 1;
592dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
594dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (checkWebCoreFeatureSupport("WML", 0)) {
595dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $supportedFileExtensions{'wml'} = 1;
596dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} else {
597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'http/tests/wml'} = 1;
598dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'fast/wml'} = 1;
599dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'wml'} = 1;
600dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
601dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
60221939df44de1705786c545cd1bf519d47250322dBen Murdochif (!checkWebCoreFeatureSupport("WCSS", 0)) {
60321939df44de1705786c545cd1bf519d47250322dBen Murdoch    $ignoredDirectories{'fast/wcss'} = 1;
60421939df44de1705786c545cd1bf519d47250322dBen Murdoch}
60521939df44de1705786c545cd1bf519d47250322dBen Murdoch
606dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!checkWebCoreFeatureSupport("XHTMLMP", 0)) {
607dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $ignoredDirectories{'fast/xhtmlmp'} = 1;
608dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
609dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
6102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochif (isAppleMacWebKit() && $platform ne "mac-wk2" && osXVersion()->{minor} >= 6 && architecture() =~ /x86_64/) {
6112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    # This test relies on executing JavaScript during NPP_Destroy, which isn't supported with
6122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    # out-of-process plugins in WebKit1. See <http://webkit.org/b/58077>.
6132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    $ignoredFiles{'plugins/npp-set-window-called-during-destruction.html'} = 1;
6142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
6152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6162bde8e466a4451c7319e3a072d118917957d6554Steve BlockprocessIgnoreTests(join(',', @ignoreTests), "ignore-tests") if @ignoreTests;
617dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (!$ignoreSkipped) {
618dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!$skippedOnly || @ARGV == 0) {
619dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        readSkippedFiles("");
620dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
621dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Since readSkippedFiles() appends to @ARGV, we must use a foreach
622dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # loop so that we only iterate over the original argument list.
623dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach my $argnum (0 .. $#ARGV) {
624dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            readSkippedFiles(shift @ARGV);
625dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
626dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
627dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
628dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
629dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @tests = findTestsToRun();
630dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
631dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockdie "no tests to run\n" if !@tests;
632dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
633dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %counts;
634dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %tests;
635dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %imagesPresent;
636dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %imageDifferences;
637dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %durations;
638dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $count = 0;
639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $leaksOutputFileNumber = 1;
640dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $totalLeaks = 0;
641dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
642dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @toolArgs = ();
643dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockpush @toolArgs, "--pixel-tests" if $pixelTests;
644dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockpush @toolArgs, "--threaded" if $threaded;
645dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockpush @toolArgs, "--complex-text" if $complexText;
646dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockpush @toolArgs, "-";
647dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
648dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @diffToolArgs = ();
649dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockpush @diffToolArgs, "--tolerance", $tolerance;
650dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
651dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$| = 1;
652dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
653dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $dumpToolPID;
654dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $isDumpToolOpen = 0;
655dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $dumpToolCrashed = 0;
656dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $imageDiffToolPID;
657dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $isDiffToolOpen = 0;
658dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
659dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $atLineStart = 1;
660dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $lastDirectory = "";
661dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
662dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $isHttpdOpen = 0;
663dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $isWebSocketServerOpen = 0;
6646c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenmy $webSocketServerPidFile = 0;
665dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $failedToStartWebSocketServer = 0;
666dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# wss is disabled until all platforms support pyOpenSSL.
667dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# my $webSocketSecureServerPID = 0;
668dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
669dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub catch_pipe { $dumpToolCrashed = 1; }
670dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$SIG{"PIPE"} = "catch_pipe";
671dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
672dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint "Testing ", scalar @tests, " test cases";
673dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint " $iterations times" if ($iterations > 1);
674dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint ", repeating each test $repeatEach times" if ($repeatEach > 1);
675dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint ".\n";
676dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
677dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $overallStartTime = time;
678dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
679dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %expectedResultPaths;
680dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
681dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @originalTests = @tests;
682dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Add individual test repetitions
683dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($repeatEach > 1) {
684dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    @tests = ();
685dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $test (@originalTests) {
686dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for (my $i = 0; $i < $repeatEach; $i++) {
687dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            push(@tests, $test);
688dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
689dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
690dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
691dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Add test set repetitions
692dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfor (my $i = 1; $i < $iterations; $i++) {
693dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push(@tests, @originalTests);
694dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
695dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
6962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochmy $absTestResultsDirectory = resolveAndMakeTestResultsDirectory();
6972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochopen my $tests_run_fh, '>', "$absTestResultsDirectory/tests_run.txt" or die $!;
6982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
699dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockfor my $test (@tests) {
700dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $newDumpTool = not $isDumpToolOpen;
701dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    openDumpTool();
702dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
703dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $base = stripExtension($test);
704dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedExtension = ".txt";
705dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
706dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $dir = $base;
707dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $dir =~ s|/[^/]+$||;
708dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
709dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($newDumpTool || $dir ne $lastDirectory) {
710dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach my $logue (epiloguesAndPrologues($newDumpTool ? "" : $lastDirectory, $dir)) {
711dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (isCygwin()) {
712dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $logue = toWindowsPath($logue);
713dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
714dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $logue = canonpath($logue);
715dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
716dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($verbose) {
717dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print "running epilogue or prologue $logue\n";
718dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
719dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print OUT "$logue\n";
720dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # Throw away output from DumpRenderTree.
721dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # Once for the test output and once for pixel results (empty)
722dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            while (<IN>) {
723dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                last if /#EOF/;
724dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
725dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            while (<IN>) {
726dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                last if /#EOF/;
727dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
728dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
729dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
730dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
731dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($verbose) {
732dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "running $test -> ";
733dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $atLineStart = 0;
734dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (!$quiet) {
735dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($dir ne $lastDirectory) {
736dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "\n" unless $atLineStart;
737dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "$dir ";
738dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
739dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print ".";
740dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $atLineStart = 0;
741dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
742dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
743dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $lastDirectory = $dir;
744dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
745dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $result;
746dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
747dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $startTime = time if $report10Slowest;
748dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
7492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    print $tests_run_fh "$testDirectory/$test\n";
7502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
751dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Try to read expected hash file for pixel tests
752dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $suffixExpectedHash = "";
753dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($pixelTests && !$resetResults) {
754dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $expectedPixelDir = expectedDirectoryForTest($base, 0, "png");
755a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (open EXPECTEDHASH, File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.checksum")) {
756dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $expectedHash = <EXPECTEDHASH>;
757dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            chomp($expectedHash);
758dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            close EXPECTEDHASH;
759dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            
760dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # Format expected hash into a suffix string that is appended to the path / URL passed to DRT
761dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $suffixExpectedHash = "'$expectedHash";
7622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        } elsif (my $expectedHash = readChecksumFromPng(File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.png"))) {
7632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            $suffixExpectedHash = "'$expectedHash";
764dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
765dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
766dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
767dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($test =~ /^http\//) {
768dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        configureAndOpenHTTPDIfNeeded();
769a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if ($test =~ /^http\/tests\/websocket\//) {
770a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if ($test =~ /^websocket\/tests\/local\//) {
771a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                my $testPath = "$testDirectory/$test";
772a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (isCygwin()) {
773a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    $testPath = toWindowsPath($testPath);
774a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                } else {
775a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    $testPath = canonpath($testPath);
776a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                }
777a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                print OUT "$testPath\n";
778a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            } else {
779a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                if (openWebSocketServerIfNeeded()) {
780a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    my $path = canonpath($test);
781a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    if ($test =~ /^http\/tests\/websocket\/tests\/ssl\//) {
782a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        # wss is disabled until all platforms support pyOpenSSL.
783a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        print STDERR "Error: wss is disabled until all platforms support pyOpenSSL.";
784a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    } else {
785a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        $path =~ s/^http\/tests\///;
786a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        print OUT "http://127.0.0.1:$httpdPort/$path\n";
787a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    }
788a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                } else {
789a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    # We failed to launch the WebSocket server.  Display a useful error message rather than attempting
790a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    # to run tests that expect the server to be available.
791a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    my $errorMessagePath = "$testDirectory/http/tests/websocket/resources/server-failed-to-start.html";
792a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    $errorMessagePath = isCygwin() ? toWindowsPath($errorMessagePath) : canonpath($errorMessagePath);
793a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    print OUT "$errorMessagePath\n";
794a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                }
795a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
79681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        } elsif ($test !~ /^http\/tests\/local\// && $test !~ /^http\/tests\/ssl\// && $test !~ /^http\/tests\/wml\//) {
797dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $path = canonpath($test);
798dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $path =~ s/^http\/tests\///;
799dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print OUT "http://127.0.0.1:$httpdPort/$path$suffixExpectedHash\n";
800dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif ($test =~ /^http\/tests\/ssl\//) {
801dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $path = canonpath($test);
802dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $path =~ s/^http\/tests\///;
803dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print OUT "https://127.0.0.1:$httpdSSLPort/$path$suffixExpectedHash\n";
804dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
805dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $testPath = "$testDirectory/$test";
806dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (isCygwin()) {
807dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $testPath = toWindowsPath($testPath);
808dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
809dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $testPath = canonpath($testPath);
810dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
811dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print OUT "$testPath$suffixExpectedHash\n";
812dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
813dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
814dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $testPath = "$testDirectory/$test";
815dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (isCygwin()) {
816dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $testPath = toWindowsPath($testPath);
817dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
818dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $testPath = canonpath($testPath);
819dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
820dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print OUT "$testPath$suffixExpectedHash\n" if defined $testPath;
821dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
822dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
823dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # DumpRenderTree is expected to dump two "blocks" to stdout for each test.
824dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Each block is terminated by a #EOF on a line by itself.
825dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # The first block is the output of the test (in text, RenderTree or other formats).
826dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # The second block is for optional pixel data in PNG format, and may be empty if
827dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # pixel tests are not being run, or the test does not dump pixels (e.g. text tests).
828dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $readResults = readFromDumpToolWithTimer(IN, ERROR);
829dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
830dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $actual = $readResults->{output};
831dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $error = $readResults->{error};
832dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
833dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $expectedExtension = $readResults->{extension};
834dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedFileName = "$base-$expectedTag.$expectedExtension";
835dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
836dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $isText = isTextOnlyTest($actual);
837dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
838dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedDir = expectedDirectoryForTest($base, $isText, $expectedExtension);
839a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    $expectedResultPaths{$base} = File::Spec->catfile($expectedDir, $expectedFileName);
840dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
841dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unless ($readResults->{status} eq "success") {
842dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $crashed = $readResults->{status} eq "crashed";
84365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        my $webProcessCrashed = $readResults->{status} eq "webProcessCrashed";
84465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        testCrashedOrTimedOut($test, $base, $crashed, $webProcessCrashed, $actual, $error);
84565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        countFinishedTest($test, $base, $webProcessCrashed ? "webProcessCrash" : $crashed ? "crash" : "timedout", 0);
846dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        last if stopRunningTestsEarlyIfNeeded();
847dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        next;
848dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
849dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
850dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $durations{$test} = time - $startTime if $report10Slowest;
851dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
852dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expected;
853dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
854a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!$resetResults && open EXPECTED, "<", $expectedResultPaths{$base}) {
855dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $expected = "";
856dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        while (<EXPECTED>) {
857dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            next if $stripEditingCallbacks && $_ =~ /^EDITING DELEGATE:/;
858dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $expected .= $_;
859dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
860dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        close EXPECTED;
861dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
862dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
863dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($ignoreMetrics && !$isText && defined $expected) {
864dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ($actual, $expected) = stripMetrics($actual, $expected);
865dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
866dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
867dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($shouldCheckLeaks && $testsPerDumpTool == 1) {
868dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "        $test -> ";
869dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
870dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
871dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $actualPNG = "";
872dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $diffPNG = "";
873dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $diffPercentage = 0;
874dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $diffResult = "passed";
875dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
876dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $actualHash = "";
877dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedHash = "";
878dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $actualPNGSize = 0;
879dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
880dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    while (<IN>) {
881dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        last if /#EOF/;
882dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (/ActualHash: ([a-f0-9]{32})/) {
883dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $actualHash = $1;
884dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif (/ExpectedHash: ([a-f0-9]{32})/) {
885dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $expectedHash = $1;
886dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif (/Content-Length: (\d+)\s*/) {
887dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $actualPNGSize = $1;
888dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            read(IN, $actualPNG, $actualPNGSize);
889dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
890dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
891dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
892dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($verbose && $pixelTests && !$resetResults && $actualPNGSize) {
893dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($actualHash eq "" && $expectedHash eq "") {
894dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            printFailureMessageForTest($test, "WARNING: actual & expected pixel hashes are missing!");
895dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif ($actualHash eq "") {
896dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            printFailureMessageForTest($test, "WARNING: actual pixel hash is missing!");
897dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif ($expectedHash eq "") {
898dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            printFailureMessageForTest($test, "WARNING: expected pixel hash is missing!");
899dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
900dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
901dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
902dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($actualPNGSize > 0) {
903dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $expectedPixelDir = expectedDirectoryForTest($base, 0, "png");
904a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        my $expectedPNGPath = File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.png");
905dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
906dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!$resetResults && ($expectedHash ne $actualHash || ($actualHash eq "" && $expectedHash eq ""))) {
907a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (-f $expectedPNGPath) {
908a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                my $expectedPNGSize = -s $expectedPNGPath;
909dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                my $expectedPNG = "";
910a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                open EXPECTEDPNG, $expectedPNGPath;
911dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                read(EXPECTEDPNG, $expectedPNG, $expectedPNGSize);
912dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
913dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                openDiffTool();
914dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFOUT "Content-Length: $actualPNGSize\n";
915dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFOUT $actualPNG;
916dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
917dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFOUT "Content-Length: $expectedPNGSize\n";
918dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFOUT $expectedPNG;
919dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
920dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                while (<DIFFIN>) {
921dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    last if /^error/ || /^diff:/;
922dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    if (/Content-Length: (\d+)\s*/) {
923dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        read(DIFFIN, $diffPNG, $1);
924dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    }
925dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
926dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
927dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (/^diff: (.+)% (passed|failed)/) {
928dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    $diffPercentage = $1 + 0;
929dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    $imageDifferences{$base} = $diffPercentage;
930dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    $diffResult = $2;
931dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
932dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                
933dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if (!$diffPercentage) {
934dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    printFailureMessageForTest($test, "pixel hash failed (but pixel test still passes)");
935dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
936dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } elsif ($verbose) {
937dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                printFailureMessageForTest($test, "WARNING: expected image is missing!");
938dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
939dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
940dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
941a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if ($resetResults || !-f $expectedPNGPath) {
942dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            mkpath catfile($expectedPixelDir, dirname($base)) if $testDirectory ne $expectedPixelDir;
943a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            writeToFile($expectedPNGPath, $actualPNG);
944dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
945dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
946a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        my $expectedChecksumPath = File::Spec->catfile($expectedPixelDir, "$base-$expectedTag.checksum");
947a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if ($actualHash ne "" && ($resetResults || !-f $expectedChecksumPath)) {
948a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            writeToFile($expectedChecksumPath, $actualHash);
949dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
950dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
951dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
952dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (dumpToolDidCrash()) {
953dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result = "crash";
95465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        testCrashedOrTimedOut($test, $base, 1, 0, $actual, $error);
955dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (!defined $expected) {
956dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($verbose) {
9576b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            print "new " . ($resetResults ? "result" : "test");
958dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
959dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result = "new";
960dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
961dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($generateNewResults || $resetResults) {
962dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            mkpath catfile($expectedDir, dirname($base)) if $testDirectory ne $expectedDir;
963dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            writeToFile("$expectedDir/$expectedFileName", $actual);
964dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
965dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        deleteExpectedAndActualResults($base);
966dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        recordActualResultsAndDiff($base, $actual);
967dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!$resetResults) {
968dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # Always print the file name for new tests, as they will probably need some manual inspection.
969dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # in verbose mode we already printed the test case, so no need to do it again.
970dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            unless ($verbose) {
971dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print "\n" unless $atLineStart;
972dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print "$test -> ";
973dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
974dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $resultsDir = catdir($expectedDir, dirname($base));
9756b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            if (!$verbose) {
9766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                print "new";
9776b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            }
978dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($generateNewResults) {
9796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner                print " (results generated in $resultsDir)";
980dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
9816b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner            print "\n" unless $atLineStart;
982dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $atLineStart = 1;
983dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
984dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif ($actual eq $expected && $diffResult eq "passed") {
985dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($verbose) {
986dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "succeeded\n";
987dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $atLineStart = 1;
988dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
989dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result = "match";
990dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        deleteExpectedAndActualResults($base);
991dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
992dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result = "mismatch";
993dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
994dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $pixelTestFailed = $pixelTests && $diffPNG && $diffPNG ne "";
995dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $testFailed = $actual ne $expected;
996dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
997dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $message = !$testFailed ? "pixel test failed" : "failed";
998dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
999dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (($testFailed || $pixelTestFailed) && $addPlatformExceptions) {
1000dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $testBase = catfile($testDirectory, $base);
1001dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $expectedBase = catfile($expectedDir, $base);
1002dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $testIsMaximallyPlatformSpecific = $testBase =~ m|^\Q$platformTestDirectory\E/|;
1003dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $expectedResultIsMaximallyPlatformSpecific = $expectedBase =~ m|^\Q$platformTestDirectory\E/|;
1004dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!$testIsMaximallyPlatformSpecific && !$expectedResultIsMaximallyPlatformSpecific) {
1005dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                mkpath catfile($platformTestDirectory, dirname($base));
1006dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if ($testFailed) {
1007dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    my $expectedFile = catfile($platformTestDirectory, "$expectedFileName");
1008dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    writeToFile("$expectedFile", $actual);
1009dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
1010dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if ($pixelTestFailed) {
1011dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    my $expectedFile = catfile($platformTestDirectory, "$base-$expectedTag.checksum");
1012dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    writeToFile("$expectedFile", $actualHash);
1013dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1014dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    $expectedFile = catfile($platformTestDirectory, "$base-$expectedTag.png");
1015dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    writeToFile("$expectedFile", $actualPNG);
1016dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
1017dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $message .= " (results generated in $platformTestDirectory)";
1018dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1019dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1020dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1021dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        printFailureMessageForTest($test, $message);
1022dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1023dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $dir = "$testResultsDirectory/$base";
1024dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $dir =~ s|/([^/]+)$|| or die "Failed to find test name from base\n";
1025dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $testName = $1;
1026dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mkpath $dir;
1027dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1028dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        deleteExpectedAndActualResults($base);
1029dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        recordActualResultsAndDiff($base, $actual);
1030dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1031dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($pixelTestFailed) {
1032dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $imagesPresent{$base} = 1;
1033dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1034dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            writeToFile("$testResultsDirectory/$base-$actualTag.png", $actualPNG);
1035dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            writeToFile("$testResultsDirectory/$base-$diffsTag.png", $diffPNG);
1036dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1037dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $expectedPixelDir = expectedDirectoryForTest($base, 0, "png");
1038dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            copy("$expectedPixelDir/$base-$expectedTag.png", "$testResultsDirectory/$base-$expectedTag.png");
1039dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1040dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            open DIFFHTML, ">$testResultsDirectory/$base-$diffsTag.html" or die;
1041dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<html>\n";
1042dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<head>\n";
1043dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<title>$base Image Compare</title>\n";
1044dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<script language=\"Javascript\" type=\"text/javascript\">\n";
1045dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "var currentImage = 0;\n";
1046dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "var imageNames = new Array(\"Actual\", \"Expected\");\n";
1047dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "var imagePaths = new Array(\"$testName-$actualTag.png\", \"$testName-$expectedTag.png\");\n";
1048dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (-f "$testDirectory/$base-w3c.png") {
1049dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                copy("$testDirectory/$base-w3c.png", "$testResultsDirectory/$base-w3c.png");
1050dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFHTML "imageNames.push(\"W3C\");\n";
1051dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFHTML "imagePaths.push(\"$testName-w3c.png\");\n";
1052dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1053dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "function animateImage() {\n";
1054dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    var image = document.getElementById(\"animatedImage\");\n";
1055dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    var imageText = document.getElementById(\"imageText\");\n";
1056dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    image.src = imagePaths[currentImage];\n";
1057dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    imageText.innerHTML = imageNames[currentImage] + \" Image\";\n";
1058dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    currentImage = (currentImage + 1) % imageNames.length;\n";
1059dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "    setTimeout('animateImage()',2000);\n";
1060dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "}\n";
1061dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</script>\n";
1062dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</head>\n";
1063dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<body onLoad=\"animateImage();\">\n";
1064dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<table>\n";
1065dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($diffPercentage) {
1066dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFHTML "<tr>\n";
1067dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFHTML "<td>Difference between images: <a href=\"$testName-$diffsTag.png\">$diffPercentage%</a></td>\n";
1068dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print DIFFHTML "</tr>\n";
1069dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1070dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<tr>\n";
1071dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<td><a href=\"" . toURL("$testDirectory/$test") . "\">test file</a></td>\n";
1072dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</tr>\n";
1073dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<tr>\n";
1074dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<td id=\"imageText\" style=\"text-weight: bold;\">Actual Image</td>\n";
1075dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</tr>\n";
1076dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<tr>\n";
1077dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "<td><img src=\"$testName-$actualTag.png\" id=\"animatedImage\"></td>\n";
1078dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</tr>\n";
1079dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</table>\n";
1080dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</body>\n";
1081dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print DIFFHTML "</html>\n";
1082dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1083dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1084dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1085dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($error) {
1086a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        my $dir = dirname(File::Spec->catdir($testResultsDirectory, $base));
1087dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mkpath $dir;
1088dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        
1089a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        writeToFile(File::Spec->catfile($testResultsDirectory, "$base-$errorTag.txt"), $error);
1090dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        
1091dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $counts{error}++;
1092dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @{$tests{error}}, $test;
1093dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1094dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1095dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    countFinishedTest($test, $base, $result, $isText);
1096dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    last if stopRunningTestsEarlyIfNeeded();
1097dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1098dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
10992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochclose($tests_run_fh);
11002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $totalTestingTime = time - $overallStartTime;
1102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy $waitTime = getWaitTime();
1103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($waitTime > 0.1) {
1104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $normalizedTestingTime = $totalTestingTime - $waitTime;
1105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    printf "\n%0.2fs HTTPD waiting time\n", $waitTime . "";
1106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    printf "%0.2fs normalized testing time", $normalizedTestingTime . "";
1107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprintf "\n%0.2fs total testing time\n", $totalTestingTime . "";
1109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block!$isDumpToolOpen || die "Failed to close $dumpToolName.\n";
1111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block$isHttpdOpen = !closeHTTPD();
1113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockcloseWebSocketServer();
1114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Because multiple instances of this script are running concurrently we cannot 
1116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# safely delete this symlink.
1117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# system "rm /tmp/LayoutTests";
1118dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# FIXME: Do we really want to check the image-comparison tool for leaks every time?
1120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($isDiffToolOpen && $shouldCheckLeaks) {
1121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $totalLeaks += countAndPrintLeaks("ImageDiff", $imageDiffToolPID, "$testResultsDirectory/ImageDiff-leaks.txt");
1122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($totalLeaks) {
1125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($mergeDepth) {
1126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        parseLeaksandPrintUniqueLeaks();
1127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else { 
1128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "\nWARNING: $totalLeaks total leaks found!\n";
1129dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "See above for individual leaks results.\n" if ($leaksOutputFileNumber > 2);
1130dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclose IN;
1134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclose OUT;
1135dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclose ERROR;
1136dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1137dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($report10Slowest) {
1138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "\n\nThe 10 slowest tests:\n\n";
1139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $count = 0;
1140dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for my $test (sort slowestcmp keys %durations) {
1141dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        printf "%0.2f secs: %s\n", $durations{$test}, $test;
1142dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        last if ++$count == 10;
1143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint "\n";
1147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($skippedOnly && $counts{"match"}) {
1149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "The following tests are in the Skipped file (" . File::Spec->abs2rel("$platformTestDirectory/Skipped", $testDirectory) . "), but succeeded:\n";
1150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $test (@{$tests{"match"}}) {
1151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "  $test\n";
1152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($resetResults || ($counts{match} && $counts{match} == $count)) {
1156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "all $count test cases succeeded\n";
1157dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unlink $testResults;
1158dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    exit;
1159dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1160dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1161dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockprintResults();
1162dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1163dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmkpath $testResultsDirectory;
1164dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1165dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockopen HTML, ">", $testResults or die "Failed to open $testResults. $!";
1166dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "<html>\n";
1167dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "<head>\n";
1168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "<title>Layout Test Results</title>\n";
1169dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "</head>\n";
1170dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "<body>\n";
1171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif ($ignoreMetrics) {
1173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print HTML "<h4>Tested with metrics ignored.</h4>";
1174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML htmlForResultsSection(@{$tests{mismatch}}, "Tests where results did not match expected results", \&linksForMismatchTest);
1177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML htmlForResultsSection(@{$tests{timedout}}, "Tests that timed out", \&linksForErrorTest);
1178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML htmlForResultsSection(@{$tests{crash}}, "Tests that caused the DumpRenderTree tool to crash", \&linksForErrorTest);
117965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochprint HTML htmlForResultsSection(@{$tests{webProcessCrash}}, "Tests that caused the Web process to crash", \&linksForErrorTest);
1180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML htmlForResultsSection(@{$tests{error}}, "Tests that had stderr output", \&linksForErrorTest);
1181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML htmlForResultsSection(@{$tests{new}}, "Tests that had no expected results (probably new)", \&linksForNewTest);
1182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
11832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprint HTML "<p>httpd access log: <a href=\"access_log.txt\">access_log.txt</a></p>\n";
11842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochprint HTML "<p>httpd error log: <a href=\"error_log.txt\">error_log.txt</a></p>\n";
11852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "</body>\n";
1187dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockprint HTML "</html>\n";
1188dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockclose HTML;
1189dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @configurationArgs = argumentsForConfiguration();
1191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockif (isGtk()) {
1193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch  system "Tools/Scripts/run-launcher", @configurationArgs, "file://".$testResults if $launchSafari;
1194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isQt()) {
1195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  unshift @configurationArgs, qw(-graphicssystem raster -style windows);
1196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  if (isCygwin()) {
1197dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $testResults = "/" . toWindowsPath($testResults);
1198dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $testResults =~ s/\\/\//g;
1199dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  }
120081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch  push(@configurationArgs, '-2') if $useWebKitTestRunner;
1201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch  system "Tools/Scripts/run-launcher", @configurationArgs, "file://".$testResults if $launchSafari;
1202dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} elsif (isCygwin()) {
1203dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block  system "cygstart", $testResults if $launchSafari;
1204a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} elsif (isWindows()) {
1205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch  system "start", $testResults if $launchSafari;
1206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block} else {
1207f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch  system "Tools/Scripts/run-safari", @configurationArgs, "-NSOpen", $testResults if $launchSafari;
1208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockcloseCygpaths() if isCygwin();
1211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockexit 1;
1213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub countAndPrintLeaks($$$)
1215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($dumpToolName, $dumpToolPID, $leaksFilePath) = @_;
1217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "\n" unless $atLineStart;
1219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $atLineStart = 1;
1220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # We are excluding the following reported leaks so they don't get in our way when looking for WebKit leaks:
1222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # This allows us ignore known leaks and only be alerted when new leaks occur. Some leaks are in the old
1223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # versions of the system frameworks that are being used by the leaks bots. Even though a leak has been
1224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # fixed, it will be listed here until the bot has been updated with the newer frameworks.
1225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1226dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @typesToExclude = (
1227dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    );
1228dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @callStacksToExclude = (
1230dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "Flash_EnforceLocalSecurity" # leaks in Flash plug-in code, rdar://problem/4449747
1231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    );
1232dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1233dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isTiger()) {
1234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Leak list for the version of Tiger used on the build bot.
1235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @callStacksToExclude, (
1236dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "CFRunLoopRunSpecific \\| malloc_zone_malloc", "CFRunLoopRunSpecific \\| CFAllocatorAllocate ", # leak in CFRunLoopRunSpecific, rdar://problem/4670839
1237dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "CGImageSourceGetPropertiesAtIndex", # leak in ImageIO, rdar://problem/4628809
1238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "FOGetCoveredUnicodeChars", # leak in ATS, rdar://problem/3943604
1239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "GetLineDirectionPreference", "InitUnicodeUtilities", # leaks tool falsely reporting leak in CFNotificationCenterAddObserver, rdar://problem/4964790
1240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "ICCFPrefWrapper::GetPrefDictionary", # leaks in Internet Config. code, rdar://problem/4449794
1241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "NSHTTPURLProtocol setResponseHeader:", # leak in multipart/mixed-replace handling in Foundation, no Radar, but fixed in Leopard
1242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "NSURLCache cachedResponseForRequest", # leak in CFURL cache, rdar://problem/4768430
1243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "PCFragPrepareClosureFromFile", # leak in Code Fragment Manager, rdar://problem/3426998
1244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "WebCore::Selection::toRange", # bug in 'leaks', rdar://problem/4967949
1245dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "WebCore::SubresourceLoader::create", # bug in 'leaks', rdar://problem/4985806
1246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_CFPreferencesDomainDeepCopyDictionary", # leak in CFPreferences, rdar://problem/4220786
1247dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_objc_msgForward", # leak in NSSpellChecker, rdar://problem/4965278
1248dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "gldGetString", # leak in OpenGL, rdar://problem/5013699
1249dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_setDefaultUserInfoFromURL", # leak in NSHTTPAuthenticator, rdar://problem/5546453 
1250dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "SSLHandshake", # leak in SSL, rdar://problem/5546440 
1251dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "SecCertificateCreateFromData", # leak in SSL code, rdar://problem/4464397
1252dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        );
1253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @typesToExclude, (
1254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "THRD", # bug in 'leaks', rdar://problem/3387783
1255dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "DRHT", # ditto (endian little hate i)
1256dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        );
1257dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isLeopard()) {
1260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Leak list for the version of Leopard used on the build bot.
1261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @callStacksToExclude, (
1262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "CFHTTPMessageAppendBytes", # leak in CFNetwork, rdar://problem/5435912
1263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "sendDidReceiveDataCallback", # leak in CFNetwork, rdar://problem/5441619
1264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_CFHTTPReadStreamReadMark", # leak in CFNetwork, rdar://problem/5441468
1265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "httpProtocolStart", # leak in CFNetwork, rdar://problem/5468837
1266dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_CFURLConnectionSendCallbacks", # leak in CFNetwork, rdar://problem/5441600
1267dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "DispatchQTMsg", # leak in QuickTime, PPC only, rdar://problem/5667132
1268dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "QTMovieContentView createVisualContext", # leak in QuickTime, PPC only, rdar://problem/5667132
1269dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "_CopyArchitecturesForJVMVersion", # leak in Java, rdar://problem/5910823
1270dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        );
1271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1273dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isSnowLeopard()) {
1274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @callStacksToExclude, (
1275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "readMakerNoteProps", # <rdar://problem/7156432> leak in ImageIO
1276dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "QTKitMovieControllerView completeUISetup", # <rdar://problem/7155156> leak in QTKit
1277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "getVMInitArgs", # <rdar://problem/7714444> leak in Java
1278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            "Java_java_lang_System_initProperties", # <rdar://problem/7714465> leak in Java
127921939df44de1705786c545cd1bf519d47250322dBen Murdoch            "glrCompExecuteKernel", # <rdar://problem/7815391> leak in graphics driver while using OpenGL
12802bde8e466a4451c7319e3a072d118917957d6554Steve Block            "NSNumberFormatter getObjectValue:forString:errorDescription:", # <rdar://problem/7149350> Leak in NSNumberFormatter
1281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        );
1282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    my $leaksTool = sourceDir() . "/Tools/Scripts/run-leaks";
1285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $excludeString = "--exclude-callstack '" . (join "' --exclude-callstack '", @callStacksToExclude) . "'";
1286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $excludeString .= " --exclude-type '" . (join "' --exclude-type '", @typesToExclude) . "'" if @typesToExclude;
1287dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print " ? checking for leaks in $dumpToolName\n";
1289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $leaksOutput = `$leaksTool $excludeString $dumpToolPID`;
1290dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($count, $bytes) = $leaksOutput =~ /Process $dumpToolPID: (\d+) leaks? for (\d+) total/;
1291dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($excluded) = $leaksOutput =~ /(\d+) leaks? excluded/;
1292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $adjustedCount = $count;
1294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $adjustedCount -= $excluded if $excluded;
1295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!$adjustedCount) {
1297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print " - no leaks found\n";
1298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        unlink $leaksFilePath;
1299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return 0;
1300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
1301dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $dir = $leaksFilePath;
1302dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $dir =~ s|/[^/]+$|| or die;
1303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mkpath $dir;
1304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($excluded) {
1306dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print " + $adjustedCount leaks ($bytes bytes including $excluded excluded leaks) were found, details in $leaksFilePath\n";
1307dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
1308dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print " + $count leaks ($bytes bytes) were found, details in $leaksFilePath\n";
1309dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1311dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        writeToFile($leaksFilePath, $leaksOutput);
1312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        
1313dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @leaksFilenames, $leaksFilePath;
1314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1315dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1316dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $adjustedCount;
1317dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1318dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1319dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub writeToFile($$)
1320dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1321dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($filePath, $contents) = @_;
1322dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    open NEWFILE, ">", "$filePath" or die "Could not create $filePath. $!\n";
1323dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print NEWFILE $contents;
1324dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    close NEWFILE;
1325dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1326dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1327dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Break up a path into the directory (with slash) and base name.
1328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub splitpath($)
1329dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1330dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($path) = @_;
1331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $pathSeparator = "/";
1333dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $dirname = dirname($path) . $pathSeparator;
1334dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $dirname = "" if $dirname eq "." . $pathSeparator;
1335dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1336dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return ($dirname, basename($path));
1337dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1338dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1339dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Sort first by directory, then by file, so all paths in one directory are grouped
1340dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# rather than being interspersed with items from subdirectories.
1341dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Use numericcmp to sort directory and filenames to make order logical.
1342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub pathcmp($$)
1343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($patha, $pathb) = @_;
1345dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1346dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($dira, $namea) = splitpath($patha);
1347dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($dirb, $nameb) = splitpath($pathb);
1348dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1349dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return numericcmp($dira, $dirb) if $dira ne $dirb;
1350dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return numericcmp($namea, $nameb);
1351dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1352dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1353dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Sort numeric parts of strings as numbers, other parts as strings.
1354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Makes 1.33 come after 1.3, which is cool.
1355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub numericcmp($$)
1356dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1357dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($aa, $bb) = @_;
1358dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1359dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @a = split /(\d+)/, $aa;
1360dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @b = split /(\d+)/, $bb;
1361dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Compare one chunk at a time.
1363dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Each chunk is either all numeric digits, or all not numeric digits.
1364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    while (@a && @b) {
1365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $a = shift @a;
1366dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $b = shift @b;
1367dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        
1368dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Use numeric comparison if chunks are non-equal numbers.
1369dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return $a <=> $b if $a =~ /^\d/ && $b =~ /^\d/ && $a != $b;
1370dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1371dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Use string comparison if chunks are any other kind of non-equal string.
1372dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return $a cmp $b if $a ne $b;
1373dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
1375dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # One of the two is now empty; compare lengths for result in this case.
1376dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @a <=> @b;
1377dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1378dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1379dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Sort slowest tests first.
1380dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub slowestcmp($$)
1381dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1382dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($testa, $testb) = @_;
1383dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1384dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $dura = $durations{$testa};
1385dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $durb = $durations{$testb};
1386dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $durb <=> $dura if $dura != $durb;
1387dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return pathcmp($testa, $testb);
1388dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1389dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub launchWithEnv(\@\%)
1391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1392dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($args, $env) = @_;
1393dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1394dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Dump the current environment as perl code and then put it in quotes so it is one parameter.
1395dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $environmentDumper = Data::Dumper->new([\%{$env}], [qw(*ENV)]);
1396dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $environmentDumper->Indent(0);
1397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $environmentDumper->Purity(1);
1398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $allEnvVars = $environmentDumper->Dump();
1399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unshift @{$args}, "\"$allEnvVars\"";
1400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1401f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    my $execScript = File::Spec->catfile(sourceDir(), qw(Tools Scripts execAppWithEnv));
1402a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    unshift @{$args}, $perlInterpreter, $execScript;
1403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @{$args};
1404dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1405dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1406dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub resolveAndMakeTestResultsDirectory()
1407dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1408dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $absTestResultsDirectory = File::Spec->rel2abs(glob $testResultsDirectory);
1409dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    mkpath $absTestResultsDirectory;
1410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $absTestResultsDirectory;
1411dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1412dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1413dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openDiffTool()
1414dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1415dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if $isDiffToolOpen;
1416dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if !$pixelTests;
1417dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1418dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my %CLEAN_ENV;
1419dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $CLEAN_ENV{MallocStackLogging} = 1 if $shouldCheckLeaks;
1420dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $imageDiffToolPID = open2(\*DIFFIN, \*DIFFOUT, $imageDiffTool, launchWithEnv(@diffToolArgs, %CLEAN_ENV)) or die "unable to open $imageDiffTool\n";
1421dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isDiffToolOpen = 1;
1422dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1423dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1424e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blocksub buildDumpTool($)
1425e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{
1426e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    my ($dumpToolName) = @_;
1427e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1428e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    my $dumpToolBuildScript =  "build-" . lc($dumpToolName);
1429e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    print STDERR "Running $dumpToolBuildScript\n";
1430e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1431e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    local *DEVNULL;
1432e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    my ($childIn, $childOut, $childErr);
1433e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if ($quiet) {
1434e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        open(DEVNULL, ">", File::Spec->devnull()) or die "Failed to open /dev/null";
1435e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        $childOut = ">&DEVNULL";
1436e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        $childErr = ">&DEVNULL";
1437e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    } else {
1438e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        # When not quiet, let the child use our stdout/stderr.
1439e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        $childOut = ">&STDOUT";
1440e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        $childErr = ">&STDERR";
1441e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
1442e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1443e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    my @args = argumentsForConfiguration();
1444f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    my $buildProcess = open3($childIn, $childOut, $childErr, $perlInterpreter, File::Spec->catfile(qw(Tools Scripts), $dumpToolBuildScript), @args) or die "Failed to run build-dumprendertree";
1445e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    close($childIn);
1446e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    waitpid $buildProcess, 0;
1447e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    my $buildResult = $?;
1448e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    close($childOut);
1449e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    close($childErr);
1450e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1451e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    close DEVNULL if ($quiet);
1452e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1453e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    if ($buildResult) {
1454e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        print STDERR "Compiling $dumpToolName failed!\n";
1455e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        exit exitStatus($buildResult);
1456e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block    }
1457e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block}
1458e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block
1459dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openDumpTool()
1460dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1461dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if $isDumpToolOpen;
1462dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
14636b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if ($verbose && $testsPerDumpTool != 1) {
14646b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        print "| Opening DumpTool |\n";
14656b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
14666b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1467dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my %CLEAN_ENV;
1468dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1469dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Generic environment variables
1470dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (defined $ENV{'WEBKIT_TESTFONTS'}) {
1471dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{WEBKIT_TESTFONTS} = $ENV{'WEBKIT_TESTFONTS'};
1472dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1473dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1474dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # unique temporary directory for each DumpRendertree - needed for running more DumpRenderTree in parallel
1475dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $CLEAN_ENV{DUMPRENDERTREE_TEMP} = File::Temp::tempdir('DumpRenderTree-XXXXXX', TMPDIR => 1, CLEANUP => 1);
1476dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $CLEAN_ENV{XML_CATALOG_FILES} = ""; # work around missing /etc/catalog <rdar://problem/4292995>
1477dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1478dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Platform spesifics
1479dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isLinux()) {
1480dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined $ENV{'DISPLAY'}) {
1481dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{DISPLAY} = $ENV{'DISPLAY'};
1482dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
1483dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{DISPLAY} = ":1";
1484dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1485dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined $ENV{'XAUTHORITY'}) {
1486dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{XAUTHORITY} = $ENV{'XAUTHORITY'};
1487dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1488dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1489dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{HOME} = $ENV{'HOME'};
149081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        $CLEAN_ENV{LANG} = $ENV{'LANG'};
1491dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1492dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined $ENV{'LD_LIBRARY_PATH'}) {
1493dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{LD_LIBRARY_PATH} = $ENV{'LD_LIBRARY_PATH'};
1494dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1495dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined $ENV{'DBUS_SESSION_BUS_ADDRESS'}) {
1496dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{DBUS_SESSION_BUS_ADDRESS} = $ENV{'DBUS_SESSION_BUS_ADDRESS'};
1497dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1498dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isDarwin()) {
1499dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined $ENV{'DYLD_LIBRARY_PATH'}) {
1500dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $CLEAN_ENV{DYLD_LIBRARY_PATH} = $ENV{'DYLD_LIBRARY_PATH'};
1501dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1502ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        if (defined $ENV{'HOME'}) {
1503ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            $CLEAN_ENV{HOME} = $ENV{'HOME'};
1504ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        }
1505dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1506dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{DYLD_FRAMEWORK_PATH} = $productDir;
1507dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{DYLD_INSERT_LIBRARIES} = "/usr/lib/libgmalloc.dylib" if $guardMalloc;
1508dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif (isCygwin()) {
1509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{HOMEDRIVE} = $ENV{'HOMEDRIVE'};
1510dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{HOMEPATH} = $ENV{'HOMEPATH'};
1511f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        $CLEAN_ENV{_NT_SYMBOL_PATH} = $ENV{_NT_SYMBOL_PATH};
1512dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1513dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        setPathForRunningWebKitApp(\%CLEAN_ENV);
1514dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1515dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1516e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    # Port specifics
1517e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if (isGtk()) {
1518e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        $CLEAN_ENV{GTK_MODULES} = "gail";
1519e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block        $CLEAN_ENV{WEBKIT_INSPECTOR_PATH} = "$productDir/resources/inspector";
1520e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
1521e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
1522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isQt()) {
1523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $CLEAN_ENV{QTWEBKIT_PLUGIN_PATH} = productDir() . "/lib/plugins";
1524545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch        $CLEAN_ENV{QT_DRT_WEBVIEW_MODE} = $ENV{"QT_DRT_WEBVIEW_MODE"};
1525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
1527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @args = ($dumpTool, @toolArgs);
1528dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isAppleMacWebKit() and !isTiger()) { 
1529dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        unshift @args, "arch", "-" . architecture();             
1530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($useValgrind) {
1533dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        unshift @args, "valgrind", "--suppressions=$platformBaseDirectory/qt/SuppressedValgrindErrors";
1534dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } 
1535dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
153628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    if ($useWebKitTestRunner) {
153728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        # Make WebKitTestRunner use a similar timeout. We don't use the exact same timeout to avoid
153828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        # race conditions.
153928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu        push @args, "--timeout", $timeoutSeconds - 5;
154028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu    }
154128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu
1542dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $CLEAN_ENV{MallocStackLogging} = 1 if $shouldCheckLeaks;
1543dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1544dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $dumpToolPID = open3(\*OUT, \*IN, \*ERROR, launchWithEnv(@args, %CLEAN_ENV)) or die "Failed to start tool: $dumpTool\n";
1545dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isDumpToolOpen = 1;
1546dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $dumpToolCrashed = 0;
1547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1548dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1549dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeDumpTool()
1550dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1551dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if !$isDumpToolOpen;
1552dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
15536b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if ($verbose && $testsPerDumpTool != 1) {
15546b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        print "| Closing DumpTool |\n";
15556b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    }
15566b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
1557dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    close IN;
1558dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    close OUT;
1559dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    waitpid $dumpToolPID, 0;
1560dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
1561dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # check for WebCore counter leaks.
1562dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($shouldCheckLeaks) {
1563dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        while (<ERROR>) {
1564dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print;
1565dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1566dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1567dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    close ERROR;
1568dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isDumpToolOpen = 0;
1569dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1570dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1571dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub dumpToolDidCrash()
1572dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1573dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 1 if $dumpToolCrashed;
1574dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 0 unless $isDumpToolOpen;
1575dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $pid = waitpid(-1, WNOHANG);
1576dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 1 if ($pid == $dumpToolPID);
1577dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1578dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # On Mac OS X, crashing may be significantly delayed by crash reporter.
1579dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 0 unless isAppleMacWebKit();
1580dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1581dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return DumpRenderTreeSupport::processIsCrashing($dumpToolPID);
1582dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1583dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1584dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub configureAndOpenHTTPDIfNeeded()
1585dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1586dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if $isHttpdOpen;
1587dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $absTestResultsDirectory = resolveAndMakeTestResultsDirectory();
1588dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $listen = "127.0.0.1:$httpdPort";
1589dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @args = (
1590dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "-c", "CustomLog \"$absTestResultsDirectory/access_log.txt\" common",
1591dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "-c", "ErrorLog \"$absTestResultsDirectory/error_log.txt\"",
1592dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "-C", "Listen $listen"
1593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    );
1594dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1595dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @defaultArgs = getDefaultConfigForTestDirectory($testDirectory);
1596dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    @args = (@defaultArgs, @args);
1597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1598dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    waitForHTTPDLock() if $shouldWaitForHTTPD;
1599dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isHttpdOpen = openHTTPD(@args);
1600dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1601dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1602545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdochsub checkPythonVersion()
1603545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch{
1604545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    # we have not chdir to sourceDir yet.
1605f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    system $perlInterpreter, File::Spec->catfile(sourceDir(), qw(Tools Scripts ensure-valid-python)), "--check-only";
1606545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch    return exitStatus($?) == 0;
1607545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch}
1608545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch
1609dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openWebSocketServerIfNeeded()
1610dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1611dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 1 if $isWebSocketServerOpen;
1612dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 0 if $failedToStartWebSocketServer;
1613dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1614dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $webSocketHandlerDir = "$testDirectory";
1615dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $absTestResultsDirectory = resolveAndMakeTestResultsDirectory();
16166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    $webSocketServerPidFile = "$absTestResultsDirectory/websocket.pid";
1617dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1618dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @args = (
1619f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        "Tools/Scripts/new-run-webkit-websocketserver",
16206c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--server", "start",
1621dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "--port", "$webSocketPort",
16226c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--root", "$webSocketHandlerDir",
16236c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--output-dir", "$absTestResultsDirectory",
16246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--pidfile", "$webSocketServerPidFile"
1625dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    );
16266c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    system "/usr/bin/python", @args;
1627dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1628dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isWebSocketServerOpen = 1;
1629dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 1;
1630dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1631dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1632dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeWebSocketServer()
1633dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1634dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return if !$isWebSocketServerOpen;
1635dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
16366c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    my @args = (
1637f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        "Tools/Scripts/new-run-webkit-websocketserver",
16386c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--server", "stop",
16396c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        "--pidfile", "$webSocketServerPidFile"
16406c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    );
16416c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    system "/usr/bin/python", @args;
16426c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    unlink "$webSocketServerPidFile";
1643dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1644dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # wss is disabled until all platforms support pyOpenSSL.
1645dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $isWebSocketServerOpen = 0;
1646dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1647dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1648dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub fileNameWithNumber($$)
1649dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1650dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($base, $number) = @_;
1651dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return "$base$number" if ($number > 1);
1652dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $base;
1653dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1654dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1655dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub processIgnoreTests($$)
1656dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1657dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @ignoreList = split(/\s*,\s*/, shift);
1658dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $listName = shift;
1659dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1660dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $disabledSuffix = "-disabled";
1661dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1662dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $addIgnoredDirectories = sub {
1663dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return () if exists $ignoredLocalDirectories{basename($File::Find::dir)};
1664dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)} = 1;
1665dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return @_;
1666dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    };
1667dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $item (@ignoreList) {
1668dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $path = catfile($testDirectory, $item); 
1669dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (-d $path) {
1670dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $ignoredDirectories{$item} = 1;
1671dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            find({ preprocess => $addIgnoredDirectories, wanted => sub {} }, $path);
1672dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1673dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        elsif (-f $path) {
1674dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $ignoredFiles{$item} = 1;
1675dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif (-f $path . $disabledSuffix) {
1676dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # The test is disabled, so do nothing.
1677dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
1678dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "$listName list contained '$item', but no file of that name could be found\n";
1679dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1680dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1681dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1682dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1683dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stripExtension($)
1684dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1685dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test) = @_;
1686dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1687dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $test =~ s/\.[a-zA-Z]+$//;
1688dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $test;
1689dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1690dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1691dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub isTextOnlyTest($)
1692dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1693dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($actual) = @_;
1694dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $isText;
1695dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($actual =~ /^layer at/ms) {
1696dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $isText = 0;
1697dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
1698dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $isText = 1;
1699dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1700dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $isText;
1701dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1702dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1703dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub expectedDirectoryForTest($;$;$)
1704dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1705dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($base, $isText, $expectedExtension) = @_;
1706dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1707dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @directories = @platformResultHierarchy;
17082bde8e466a4451c7319e3a072d118917957d6554Steve Block
17092bde8e466a4451c7319e3a072d118917957d6554Steve Block    my @extraPlatforms = ();
17102bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (isAppleWinWebKit()) {
17112bde8e466a4451c7319e3a072d118917957d6554Steve Block        push @extraPlatforms, "mac-wk2" if $platform eq "win-wk2";
17122bde8e466a4451c7319e3a072d118917957d6554Steve Block        push @extraPlatforms, qw(mac-snowleopard mac);
17132bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
17142bde8e466a4451c7319e3a072d118917957d6554Steve Block  
17152bde8e466a4451c7319e3a072d118917957d6554Steve Block    push @directories, map { catdir($platformBaseDirectory, $_) } @extraPlatforms;
1716dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @directories, $expectedDirectory;
1717dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1718dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # If we already have expected results, just return their location.
1719dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $directory (@directories) {
1720a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return $directory if -f File::Spec->catfile($directory, "$base-$expectedTag.$expectedExtension");
1721dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1722dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1723dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # For cross-platform tests, text-only results should go in the cross-platform directory,
1724dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # while render tree dumps should go in the least-specific platform directory.
1725dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $isText ? $expectedDirectory : $platformResultHierarchy[$#platformResultHierarchy];
1726dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1727dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1728dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub countFinishedTest($$$$)
1729dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1730dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test, $base, $result, $isText) = @_;
1731dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1732dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (($count + 1) % $testsPerDumpTool == 0 || $count == $#tests) {
1733dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($shouldCheckLeaks) {
1734dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $fileName;
1735dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($testsPerDumpTool == 1) {
1736a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                $fileName = File::Spec->catfile($testResultsDirectory, "$base-leaks.txt");
1737dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
1738a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                $fileName = File::Spec->catfile($testResultsDirectory, fileNameWithNumber($dumpToolName, $leaksOutputFileNumber) . "-leaks.txt");
1739dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
1740dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $leakCount = countAndPrintLeaks($dumpToolName, $dumpToolPID, $fileName);
1741dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $totalLeaks += $leakCount;
1742dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $leaksOutputFileNumber++ if ($leakCount);
1743dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1744dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1745dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        closeDumpTool();
1746dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1747dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
1748dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $count++;
1749dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $counts{$result}++;
1750dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @{$tests{$result}}, $test;
1751dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1752dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
175365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochsub testCrashedOrTimedOut($$$$$$)
1754dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
175565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    my ($test, $base, $didCrash, $webProcessCrashed, $actual, $error) = @_;
1756dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
175765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    printFailureMessageForTest($test, $webProcessCrashed ? "Web process crashed" : $didCrash ? "crashed" : "timed out");
1758dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
175965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    sampleDumpTool() unless $didCrash || $webProcessCrashed;
1760dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1761a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    my $dir = dirname(File::Spec->catdir($testResultsDirectory, $base));
1762dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    mkpath $dir;
1763dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1764dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    deleteExpectedAndActualResults($base);
1765dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1766dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (defined($error) && length($error)) {
1767a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        writeToFile(File::Spec->catfile($testResultsDirectory, "$base-$errorTag.txt"), $error);
1768dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1769dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1770dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    recordActualResultsAndDiff($base, $actual);
1771dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
177281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    # There's no point in killing the dump tool when it's crashed. And it will kill itself when the
177381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    # web process crashes.
177481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    kill 9, $dumpToolPID unless $didCrash || $webProcessCrashed;
1775dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1776dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    closeDumpTool();
17772fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
177881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    captureSavedCrashLog($base, $webProcessCrashed) if $didCrash || $webProcessCrashed;
17792fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1780967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    return unless isCygwin() && !$didCrash && $base =~ /^http/;
1781967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    # On Cygwin, http tests timing out can be a symptom of a non-responsive httpd.
1782967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    # If we timed out running an http test, try restarting httpd.
1783967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    $isHttpdOpen = !closeHTTPD();
1784967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    configureAndOpenHTTPDIfNeeded();
1785dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1786dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
178781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochsub captureSavedCrashLog($$)
17882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
178981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    my ($base, $webProcessCrashed) = @_;
17902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
17912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $crashLog;
17922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
17932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $glob;
17942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isCygwin()) {
17952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        $glob = File::Spec->catfile($testResultsDirectory, $windowsCrashLogFilePrefix . "*.txt");
17962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    } elsif (isAppleMacWebKit()) {
179781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        my $crashLogDirectoryName;
179881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (isTiger() || isLeopard()) {
179981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            $crashLogDirectoryName = "CrashReporter";
180081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        } else {
180181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            $crashLogDirectoryName = "DiagnosticReports";
180281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
180381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
180481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        $glob = File::Spec->catfile("~", "Library", "Logs", $crashLogDirectoryName, ($webProcessCrashed ? "WebProcess" : $dumpToolName) . "_*.crash");
18052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # Even though the dump tool has exited, CrashReporter might still be running. We need to
18072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # wait for it to exit to ensure it has saved its crash log to disk. For simplicitly, we'll
18082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # assume that the ReportCrash process with the highest PID is the one we want.
18092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (my @reportCrashPIDs = sort map { /^\s*(\d+)/; $1 } grep { /ReportCrash/ } `/bin/ps x`) {
18102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            my $reportCrashPID = $reportCrashPIDs[$#reportCrashPIDs];
18112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            # We use kill instead of waitpid because ReportCrash is not one of our child processes.
18122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            usleep(250000) while kill(0, $reportCrashPID) > 0;
18132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
18142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
18152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
181681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return unless $glob;
181781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
18182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # We assume that the newest crash log in matching the glob is the one that corresponds to the crash that just occurred.
18192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (my $newestCrashLog = findNewestFileMatchingGlob($glob)) {
18202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # The crash log must have been created after this script started running.
18212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        $crashLog = $newestCrashLog if -M $newestCrashLog < 0;
18222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
18232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return unless $crashLog;
18252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    move($crashLog, File::Spec->catfile($testResultsDirectory, "$base-$crashLogTag.txt"));
18272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
18282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18292fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocksub findNewestFileMatchingGlob($)
18302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
18312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my ($glob) = @_;
18322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my @paths = glob $glob;
183481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return unless scalar(@paths);
18352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
18362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my @pathsAndTimes = map { [$_, -M $_] } @paths;
18372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    @pathsAndTimes = sort { $b->[1] <=> $a->[1] } @pathsAndTimes;
18382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return $pathsAndTimes[$#pathsAndTimes]->[0];
18392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
18402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1841dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub printFailureMessageForTest($$)
1842dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1843dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test, $description) = @_;
1844dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1845dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unless ($verbose) {
1846dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "\n" unless $atLineStart;
1847dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print "$test -> ";
1848dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1849dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "$description\n";
1850dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $atLineStart = 1;
1851dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1852dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1853dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy %cygpaths = ();
1854dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1855dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub openCygpathIfNeeded($)
1856dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1857dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($options) = @_;
1858dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1859dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless isCygwin();
1860dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $cygpaths{$options} if $cygpaths{$options} && $cygpaths{$options}->{"open"};
1861dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1862dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    local (*CYGPATHIN, *CYGPATHOUT);
1863dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $pid = open2(\*CYGPATHIN, \*CYGPATHOUT, "cygpath -f - $options");
1864dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $cygpath =  {
1865dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "pid" => $pid,
1866dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "in" => *CYGPATHIN,
1867dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "out" => *CYGPATHOUT,
1868dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        "open" => 1
1869dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    };
1870dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1871dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $cygpaths{$options} = $cygpath;
1872dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1873dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $cygpath;
1874dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1875dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1876dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub closeCygpaths()
1877dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1878dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless isCygwin();
1879dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1880dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $cygpath (values(%cygpaths)) {
1881dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        close $cygpath->{"in"};
1882dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        close $cygpath->{"out"};
1883dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        waitpid($cygpath->{"pid"}, 0);
1884dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $cygpath->{"open"} = 0;
1885dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1886dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1887dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1888dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1889dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub convertPathUsingCygpath($$)
1890dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1891dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($path, $options) = @_;
1892dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1893dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # cygpath -f (at least in Cygwin 1.7) converts spaces into newlines. We remove spaces here and
1894dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # add them back in after conversion to work around this.
1895dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $spaceSubstitute = "__NOTASPACE__";
1896dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $path =~ s/ /\Q$spaceSubstitute\E/g;
1897dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1898dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $cygpath = openCygpathIfNeeded($options);
1899dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    local *inFH = $cygpath->{"in"};
1900dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    local *outFH = $cygpath->{"out"};
1901dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print outFH $path . "\n";
1902dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $convertedPath = <inFH>;
1903dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    chomp($convertedPath) if defined $convertedPath;
1904dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1905dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $convertedPath =~ s/\Q$spaceSubstitute\E/ /g;
1906dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $convertedPath;
1907dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1908dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1909f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksub toCygwinPath($)
1910f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
1911f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    my ($path) = @_;
1912f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return unless isCygwin();
1913f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1914f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return convertPathUsingCygpath($path, "-u");
1915f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
1916f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1917dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub toWindowsPath($)
1918dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1919dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($path) = @_;
1920dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless isCygwin();
1921dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1922dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return convertPathUsingCygpath($path, "-w");
1923dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1924dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1925dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub toURL($)
1926dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1927dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($path) = @_;
1928dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1929dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($useRemoteLinksToTests) {
1930dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $relativePath = File::Spec->abs2rel($path, $testDirectory);
1931dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1932dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # If the file is below the test directory then convert it into a link to the file in SVN
1933dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($relativePath !~ /^\.\.\//) {
1934dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $revision = svnRevisionForDirectory($testDirectory);
1935dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $svnPath = pathRelativeToSVNRepositoryRootForPath($path);
1936dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return "http://trac.webkit.org/export/$revision/$svnPath";
1937dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1938dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1939dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1940dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return $path unless isCygwin();
1941dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1942dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return "file:///" . convertPathUsingCygpath($path, "-m");
1943dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1944dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1945dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub validateSkippedArg($$;$)
1946dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1947dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($option, $value, $value2) = @_;
1948dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my %validSkippedValues = map { $_ => 1 } qw(default ignore only);
1949dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $value = lc($value);
1950dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    die "Invalid argument '" . $value . "' for option $option" unless $validSkippedValues{$value};
1951dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    $treatSkipped = $value;
1952dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1953dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1954dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub htmlForResultsSection(\@$&)
1955dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1956dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($tests, $description, $linkGetter) = @_;
1957dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1958dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @html = ();
1959dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return join("\n", @html) unless @{$tests};
1960dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1961dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @html, "<p>$description:</p>";
1962dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @html, "<table>";
1963dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $test (@{$tests}) {
1964dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @html, "<tr>";
1965dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @html, "<td><a href=\"" . toURL("$testDirectory/$test") . "\">$test</a></td>";
1966dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach my $link (@{&{$linkGetter}($test)}) {
19672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            push @html, "<td>";
19682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            push @html, "<a href=\"$link->{href}\">$link->{text}</a>" if -f File::Spec->catfile($testResultsDirectory, $link->{href});
19692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            push @html, "</td>";
1970dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
1971dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @html, "</tr>";
1972dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
1973dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @html, "</table>";
1974dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1975dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return join("\n", @html);
1976dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1977dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1978dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub linksForExpectedAndActualResults($)
1979dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1980dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($base) = @_;
1981dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1982dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @links = ();
1983dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1984dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links unless -s "$testResultsDirectory/$base-$diffsTag.txt";
1985dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
1986dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedResultPath = $expectedResultPaths{$base};
1987dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($expectedResultFileName, $expectedResultsDirectory, $expectedResultExtension) = fileparse($expectedResultPath, qr{\.[^.]+$});
1988dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1989dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$expectedTag$expectedResultExtension", text => "expected" };
1990dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$actualTag$expectedResultExtension", text => "actual" };
1991dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$diffsTag.txt", text => "diff" };
1992dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$prettyDiffTag.html", text => "pretty diff" };
1993dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1994dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links;
1995dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
1996dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
1997dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub linksForMismatchTest
1998dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
1999dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test) = @_;
2000dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2001dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @links = ();
2002dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2003dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $base = stripExtension($test);
2004dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2005dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, @{linksForExpectedAndActualResults($base)};
2006dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links unless $pixelTests && $imagesPresent{$base};
2007dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2008dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$expectedTag.png", text => "expected image" };
2009dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$diffsTag.html", text => "image diffs" };
2010dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$diffsTag.png", text => "$imageDifferences{$base}%" };
2011dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2012dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links;
2013dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2014dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
20152fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocksub crashLocation($)
20162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
20172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my ($base) = @_;
20182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $crashLogFile = File::Spec->catfile($testResultsDirectory, "$base-$crashLogTag.txt");
20202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isCygwin()) {
20222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # We're looking for the following text:
20232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        #
20242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # FOLLOWUP_IP:
20252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # module!function+offset [file:line]
20262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        #
20272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # The second contains the function that crashed (or the function that ended up jumping to a bad
20282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # address, as in the case of a null function pointer).
20292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20302fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        open LOG, "<", $crashLogFile or return;
20312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        while (my $line = <LOG>) {
20322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            last if $line =~ /^FOLLOWUP_IP:/;
20332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
20342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        my $desiredLine = <LOG>;
20352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        close LOG;
20362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return unless $desiredLine;
20382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # Just take everything up to the first space (which is where the file/line information should
20402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # start).
20412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        $desiredLine =~ /^(\S+)/;
20422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return $1;
20432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
20442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (isAppleMacWebKit()) {
20462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # We're looking for the following text:
20472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        #
20482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # Thread M Crashed:
20492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # N   module                              address function + offset (file:line)
20502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        #
20512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # Some lines might have a module of "???" if we've jumped to a bad address. We should skip
20522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        # past those.
20532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
20542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        open LOG, "<", $crashLogFile or return;
20552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        while (my $line = <LOG>) {
20562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            last if $line =~ /^Thread \d+ Crashed:/;
20572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
20582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        my $location;
20592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        while (my $line = <LOG>) {
20602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            $line =~ /^\d+\s+(\S+)\s+\S+ (.* \+ \d+)/ or next;
20612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            my $module = $1;
20622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            my $functionAndOffset = $2;
20632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            next if $module eq "???";
20642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            $location = "$module: $functionAndOffset";
20652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            last;
20662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        }
20672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        close LOG;
20682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return $location;
20692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
20702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
20712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2072dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub linksForErrorTest
2073dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2074dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test) = @_;
2075dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2076dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @links = ();
2077dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2078dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $base = stripExtension($test);
2079dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
20802fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $crashLogText = "crash log";
20812fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (my $crashLocation = crashLocation($base)) {
20822bde8e466a4451c7319e3a072d118917957d6554Steve Block        $crashLogText .= " (<code>" . CGI::escapeHTML($crashLocation) . "</code>)";
20832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
20842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2085dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, @{linksForExpectedAndActualResults($base)};
2086dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$errorTag.txt", text => "stderr" };
20872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    push @links, { href => "$base-$crashLogTag.txt", text => $crashLogText };
2088dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2089dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links;
2090dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2091dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2092dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub linksForNewTest
2093dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2094dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($test) = @_;
2095dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2096dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @links = ();
2097dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2098dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $base = stripExtension($test);
2099dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2100dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedResultPath = $expectedResultPaths{$base};
2101dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($expectedResultFileName, $expectedResultsDirectory, $expectedResultExtension) = fileparse($expectedResultPath, qr{\.[^.]+$});
2102dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2103dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    push @links, { href => "$base-$actualTag$expectedResultExtension", text => "result" };
2104dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($pixelTests && $imagesPresent{$base}) {
2105dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @links, { href => "$base-$expectedTag.png", text => "image" };
2106dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2107dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2108dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return \@links;
2109dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2110dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2111dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub deleteExpectedAndActualResults($)
2112dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2113dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($base) = @_;
2114dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2115dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unlink "$testResultsDirectory/$base-$actualTag.txt";
2116dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unlink "$testResultsDirectory/$base-$diffsTag.txt";
2117dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    unlink "$testResultsDirectory/$base-$errorTag.txt";
21182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unlink "$testResultsDirectory/$base-$crashLogTag.txt";
2119dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2120dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2121dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub recordActualResultsAndDiff($$)
2122dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2123dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($base, $actualResults) = @_;
2124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2125dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless defined($actualResults) && length($actualResults);
2126dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2127dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $expectedResultPath = $expectedResultPaths{$base};
2128dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($expectedResultFileNameMinusExtension, $expectedResultDirectoryPath, $expectedResultExtension) = fileparse($expectedResultPath, qr{\.[^.]+$});
2129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    my $actualResultsPath = File::Spec->catfile($testResultsDirectory, "$base-$actualTag$expectedResultExtension");
2130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    my $copiedExpectedResultsPath = File::Spec->catfile($testResultsDirectory, "$base-$expectedTag$expectedResultExtension");
2131dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2132dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    mkpath(dirname($actualResultsPath));
2133dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    writeToFile("$actualResultsPath", $actualResults);
2134dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
21352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    # We don't need diff and pretty diff for tests without expected file.
21362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if ( !-f $expectedResultPath) {
21372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
2138dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2139dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
21402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    copy("$expectedResultPath", "$copiedExpectedResultsPath");
21412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    my $diffOuputBasePath = File::Spec->catfile($testResultsDirectory, $base);
2143dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $diffOutputPath = "$diffOuputBasePath-$diffsTag.txt";
2144dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    system "diff -u \"$copiedExpectedResultsPath\" \"$actualResultsPath\" > \"$diffOutputPath\"";
2145dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2146dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $prettyDiffOutputPath = "$diffOuputBasePath-$prettyDiffTag.html";
2147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    my $prettyPatchPath = "Websites/bugs.webkit.org/PrettyPatch/";
2148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $prettifyPath = "$prettyPatchPath/prettify.rb";
2149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    system "ruby -I \"$prettyPatchPath\" \"$prettifyPath\" \"$diffOutputPath\" > \"$prettyDiffOutputPath\"";
2150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub buildPlatformResultHierarchy()
2153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    mkpath($platformTestDirectory) if ($platform eq "undefined" && !-d "$platformTestDirectory");
2155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @platforms;
2157e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    
2158e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    my $isMac = $platform =~ /^mac/;
2159e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    my $isWin = $platform =~ /^win/;
2160e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if ($isMac || $isWin) {
2161e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        my $effectivePlatform = $platform;
2162db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        if ($platform eq "mac-wk2" || $platform eq "win-wk2") {
2163db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            push @platforms, $platform;
2164e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            $effectivePlatform = $realPlatform;
2165e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        }
2166e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
2167e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        my @platformList = $isMac ? @macPlatforms : @winPlatforms;
2168dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $i;
2169e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        for ($i = 0; $i < @platformList; $i++) {
2170e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            last if $platformList[$i] eq $effectivePlatform;
2171dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2172e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        for (; $i < @platformList; $i++) {
2173e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            push @platforms, $platformList[$i];
2174dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2175dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif ($platform =~ /^qt-/) {
2176dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @platforms, $platform;
2177dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @platforms, "qt";
2178dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
2179dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        @platforms = $platform;
2180dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2181dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2182dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @hierarchy;
2183dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (my $i = 0; $i < @platforms; $i++) {
2184dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $scoped = catdir($platformBaseDirectory, $platforms[$i]);
2185dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push(@hierarchy, $scoped) if (-d $scoped);
2186dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2187e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    
21882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    unshift @hierarchy, grep { -d $_ } @additionalPlatformDirectories;
21892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2190dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @hierarchy;
2191dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2192dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2193dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub buildPlatformTestHierarchy(@)
2194dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2195dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my (@platformHierarchy) = @_;
2196dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @platformHierarchy if (@platformHierarchy < 2);
2197e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if ($platformHierarchy[0] =~ /mac-wk2/) {
2198e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return ($platformHierarchy[0], $platformHierarchy[1], $platformHierarchy[$#platformHierarchy]);
2199e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
2200dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return ($platformHierarchy[0], $platformHierarchy[$#platformHierarchy]);
2201dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2202dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2203dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub epiloguesAndPrologues($$)
2204dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2205dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($lastDirectory, $directory) = @_;
2206dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @lastComponents = split('/', $lastDirectory);
2207dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @components = split('/', $directory);
2208dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2209dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    while (@lastComponents) {
2210dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!defined($components[0]) || $lastComponents[0] ne $components[0]) {
2211dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            last;
2212dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2213dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        shift @components;
2214dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        shift @lastComponents;
2215dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2216dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2217dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @result;
2218dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $leaving = $lastDirectory;
2219dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach (@lastComponents) {
2220dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $epilogue = $leaving . "/resources/run-webkit-tests-epilogue.html";
2221dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach (@platformResultHierarchy) {
2222dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            push @result, catdir($_, $epilogue) if (stat(catdir($_, $epilogue)));
2223dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2224dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @result, catdir($testDirectory, $epilogue) if (stat(catdir($testDirectory, $epilogue)));
2225dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $leaving =~ s|(^\|/)[^/]+$||;
2226dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2227dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2228dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $entering = $leaving;
2229dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach (@components) {
2230dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $entering .= '/' . $_;
2231dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $prologue = $entering . "/resources/run-webkit-tests-prologue.html";
2232dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @result, catdir($testDirectory, $prologue) if (stat(catdir($testDirectory, $prologue)));
2233dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach (reverse @platformResultHierarchy) {
2234dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            push @result, catdir($_, $prologue) if (stat(catdir($_, $prologue)));
2235dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2236dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2237dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @result;
2238dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2239dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
2240dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub parseLeaksandPrintUniqueLeaks()
2241dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2242dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless @leaksFilenames;
2243dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block     
2244dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $mergedFilenames = join " ", @leaksFilenames;
2245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    my $parseMallocHistoryTool = sourceDir() . "/Tools/Scripts/parse-malloc-history";
2246dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
2247dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    open MERGED_LEAKS, "cat $mergedFilenames | $parseMallocHistoryTool --merge-depth $mergeDepth  - |" ;
2248dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @leakLines = <MERGED_LEAKS>;
2249dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    close MERGED_LEAKS;
2250dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
2251dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $uniqueLeakCount = 0;
2252dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $totalBytes;
2253dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $line (@leakLines) {
2254dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        ++$uniqueLeakCount if ($line =~ /^(\d*)\scalls/);
2255dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $totalBytes = $1 if $line =~ /^total\:\s(.*)\s\(/;
2256dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2257dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
2258dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "\nWARNING: $totalLeaks total leaks found for a total of $totalBytes!\n";
2259dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "WARNING: $uniqueLeakCount unique leaks found!\n";
2260dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    print "See above for individual leaks results.\n" if ($leaksOutputFileNumber > 2);
2261dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    
2262dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2263dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2264dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub extensionForMimeType($)
2265dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2266dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($mimeType) = @_;
2267dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2268dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($mimeType eq "application/x-webarchive") {
2269dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return "webarchive";
2270dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } elsif ($mimeType eq "application/pdf") {
2271dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return "pdf";
2272dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2273dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return "txt";
2274dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2275dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2276dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block# Read up to the first #EOF (the content block of the test), or until detecting crashes or timeouts.
2277dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub readFromDumpToolWithTimer(**)
2278dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2279dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($fhIn, $fhError) = @_;
2280dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2281dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    setFileHandleNonBlocking($fhIn, 1);
2282dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    setFileHandleNonBlocking($fhError, 1);
2283dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2284dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $maximumSecondsWithoutOutput = $timeoutSeconds;
2285dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $microsecondsToWaitBeforeReadingAgain = 1000;
2286dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2287dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $timeOfLastSuccessfulRead = time;
2288dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2289dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @output = ();
2290dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @error = ();
2291dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $status = "success";
2292dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $mimeType = "text/plain";
2293dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # We don't have a very good way to know when the "headers" stop
2294dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # and the content starts, so we use this as a hack:
2295dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $haveSeenContentType = 0;
2296dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $haveSeenEofIn = 0;
2297dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $haveSeenEofError = 0;
2298dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2299dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    while (1) {
2300dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (time - $timeOfLastSuccessfulRead > $maximumSecondsWithoutOutput) {
2301dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $status = dumpToolDidCrash() ? "crashed" : "timedOut";
2302dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            last;
2303dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2304dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2305dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # Once we've seen the EOF, we must not read anymore.
2306dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $lineIn = readline($fhIn) unless $haveSeenEofIn;
2307dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $lineError = readline($fhError) unless $haveSeenEofError;
2308dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (!defined($lineIn) && !defined($lineError)) {
2309dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            last if ($haveSeenEofIn && $haveSeenEofError);
2310dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2311dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($! != EAGAIN) {
2312dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $status = "crashed";
2313dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                last;
2314dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2315dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2316dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            # No data ready
2317dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            usleep($microsecondsToWaitBeforeReadingAgain);
2318dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            next;
2319dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2320dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2321dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $timeOfLastSuccessfulRead = time;
2322dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2323dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined($lineIn)) {
2324dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!$haveSeenContentType && $lineIn =~ /^Content-Type: (\S+)$/) {
2325dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $mimeType = $1;
2326dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $haveSeenContentType = 1;
2327dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } elsif ($lineIn =~ /#EOF/) {
2328dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $haveSeenEofIn = 1;
2329dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
2330dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push @output, $lineIn;
2331dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2332dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2333dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (defined($lineError)) {
233465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            if ($lineError =~ /#CRASHED - WebProcess/) {
233565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                $status = "webProcessCrashed";
233665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                last;
233765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            }
2338f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            if ($lineError =~ /#CRASHED/) {
2339f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick                $status = "crashed";
2340f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick                last;
2341f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            }
2342dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($lineError =~ /#EOF/) {
2343dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $haveSeenEofError = 1;
2344dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
2345dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push @error, $lineError;
2346dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2347dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2348dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2349dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2350dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    setFileHandleNonBlocking($fhIn, 0);
2351dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    setFileHandleNonBlocking($fhError, 0);
2352dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return {
2353dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        output => join("", @output),
2354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        error => join("", @error),
2355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        status => $status,
2356dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mimeType => $mimeType,
2357dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        extension => extensionForMimeType($mimeType)
2358dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    };
2359dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2360dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2361dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub setFileHandleNonBlocking(*$)
2362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2363dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($fh, $nonBlocking) = @_;
2364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $flags = fcntl($fh, F_GETFL, 0) or die "Couldn't get filehandle flags";
2366dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2367dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($nonBlocking) {
2368dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $flags |= O_NONBLOCK;
2369dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    } else {
2370dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $flags &= ~O_NONBLOCK;
2371dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2372dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2373dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    fcntl($fh, F_SETFL, $flags) or die "Couldn't set filehandle flags";
2374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2375dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 1;
2376dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2377dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2378dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub sampleDumpTool()
2379dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2380dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless isAppleMacWebKit();
2381dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return unless $runSample;
2382dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2383dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $outputDirectory = "$ENV{HOME}/Library/Logs/DumpRenderTree";
2384dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    -d $outputDirectory or mkdir $outputDirectory;
2385dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2386dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $outputFile = "$outputDirectory/HangReport.txt";
2387dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    system "/usr/bin/sample", $dumpToolPID, qw(10 10 -file), $outputFile;
2388dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2389dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stripMetrics($$)
2391dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2392dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($actual, $expected) = @_;
2393dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2394dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $result ($actual, $expected) {
2395dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g;
2396dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/size -?[0-9]+x-?[0-9]+ *//g;
2397dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/text run width -?[0-9]+: //g;
2398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g;
2399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g;
2400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g;
2401dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g;
2402dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g;
2403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/\([0-9]+px/px/g;
2404dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/ *" *\n +" */ /g;
2405dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/" +$/"/g;
2406dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2407dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/- /-/g;
2408dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/\n( *)"\s+/\n$1"/g;
2409dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/\s+"\n/"\n/g;
2410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/scrollWidth [0-9]+/scrollWidth/g;
2411dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $result =~ s/scrollHeight [0-9]+/scrollHeight/g;
2412dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2413dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2414dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return ($actual, $expected);
2415dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2416dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2417dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub fileShouldBeIgnored
2418dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2419dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($filePath) = @_;
2420dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    foreach my $ignoredDir (keys %ignoredDirectories) {
2421dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($filePath =~ m/^$ignoredDir/) {
2422dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            return 1;
2423dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2424dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2425dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return 0;
2426dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2427dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2428dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub readSkippedFiles($)
2429dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2430dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my ($constraintPath) = @_;
2431dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2432dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    my @skippedFileDirectories = @platformTestHierarchy;
2433dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2434dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    # Because nearly all of the skipped tests for WebKit 2 on Mac are due to
2435dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    # cross-platform issues, Windows will use both the Mac and Windows skipped
2436dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    # lists to avoid maintaining separate lists.
2437dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    push(@skippedFileDirectories, catdir($platformBaseDirectory, "mac-wk2")) if $platform eq "win-wk2";
2438dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch
2439dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    foreach my $level (@skippedFileDirectories) {
2440dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (open SKIPPED, "<", "$level/Skipped") {
2441dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($verbose) {
2442dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                my ($dir, $name) = splitpath($level);
2443dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print "Skipped tests in $name:\n";
2444dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2445dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2446dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            while (<SKIPPED>) {
2447dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                my $skipped = $_;
2448dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                chomp $skipped;
2449dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $skipped =~ s/^[ \n\r]+//;
2450dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                $skipped =~ s/[ \n\r]+$//;
2451dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                if ($skipped && $skipped !~ /^#/) {
2452dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    if ($skippedOnly) {
2453dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        if (!fileShouldBeIgnored($skipped)) {
2454dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            if (!$constraintPath) {
2455dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                # Always add $skipped since no constraint path was specified on the command line.
2456dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                push(@ARGV, $skipped);
2457dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            } elsif ($skipped =~ /^($constraintPath)/) {
2458dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                # Add $skipped only if it matches the current path constraint, e.g.,
2459dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                # "--skipped=only dir1" with "dir1/file1.html" on the skipped list.
2460dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                push(@ARGV, $skipped);
2461dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            } elsif ($constraintPath =~ /^($skipped)/) {
2462dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                # Add current path constraint if it is more specific than the skip list entry,
2463dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                # e.g., "--skipped=only dir1/dir2/dir3" with "dir1" on the skipped list.
2464dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                                push(@ARGV, $constraintPath);
2465dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            }
2466dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        } elsif ($verbose) {
2467dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            print "    $skipped\n";
2468dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        }
2469dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    } else {
2470dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        if ($verbose) {
2471dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                            print "    $skipped\n";
2472dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        }
2473dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                        processIgnoreTests($skipped, "Skipped");
2474dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                    }
2475dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                }
2476dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2477dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            close SKIPPED;
2478dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2479dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2480dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2481dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
24822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochsub readChecksumFromPng($)
24832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
24842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    my ($path) = @_;
24852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    my $data;
24862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (open(PNGFILE, $path) && read(PNGFILE, $data, 2048) && $data =~ /tEXtchecksum\0([a-fA-F0-9]{32})/) {
24872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return $1;
24882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
24892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
24902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2491dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockmy @testsFound;
2492dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
24932bde8e466a4451c7319e3a072d118917957d6554Steve Blocksub isUsedInReftest
24942bde8e466a4451c7319e3a072d118917957d6554Steve Block{
24952bde8e466a4451c7319e3a072d118917957d6554Steve Block    my $filename = $_;
24962bde8e466a4451c7319e3a072d118917957d6554Steve Block    if ($filename =~ /-$expectedTag(-$mismatchTag)?\.html$/) {
24972bde8e466a4451c7319e3a072d118917957d6554Steve Block        return 1;
24982bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
24992bde8e466a4451c7319e3a072d118917957d6554Steve Block    my $base = stripExtension($filename);
25002bde8e466a4451c7319e3a072d118917957d6554Steve Block    return (-f "$base-$expectedTag.html" || -f "$base-$expectedTag-$mismatchTag.html");
25012bde8e466a4451c7319e3a072d118917957d6554Steve Block}
25022bde8e466a4451c7319e3a072d118917957d6554Steve Block
2503dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub directoryFilter
2504dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2505dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return () if exists $ignoredLocalDirectories{basename($File::Find::dir)};
2506dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return () if exists $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)};
2507dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @_;
2508dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2509dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2510dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub fileFilter
2511dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2512dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $filename = $_;
2513dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if ($filename =~ /\.([^.]+)$/) {
25142bde8e466a4451c7319e3a072d118917957d6554Steve Block        my $extension = $1;
25152bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (exists $supportedFileExtensions{$extension} && !isUsedInReftest($filename)) {
2516dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my $path = File::Spec->abs2rel(catfile($File::Find::dir, $filename), $testDirectory);
2517dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            push @testsFound, $path if !exists $ignoredFiles{$path};
2518dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2519dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2520dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2521dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2522dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub findTestsToRun
2523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2524dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my @testsToRun = ();
2525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for my $test (@ARGV) {
2527a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        $test =~ s/^(\Q$layoutTestsName\E|\Q$testDirectory\E)\///;
2528dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $fullPath = catfile($testDirectory, $test);
2529dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (file_name_is_absolute($test)) {
2530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "can't run test $test outside $testDirectory\n";
2531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif (-f $fullPath) {
2532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            my ($filename, $pathname, $fileExtension) = fileparse($test, qr{\.[^.]+$});
2533dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (!exists $supportedFileExtensions{substr($fileExtension, 1)}) {
2534dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                print "test $test does not have a supported extension\n";
2535dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } elsif ($testHTTP || $pathname !~ /^http\//) {
2536dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push @testsToRun, $test;
2537dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2538dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } elsif (-d $fullPath) {
2539dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            @testsFound = ();
2540dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $fullPath);
2541dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            for my $level (@platformTestHierarchy) {
2542dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                my $platformPath = catfile($level, $test);
2543dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $platformPath) if (-d $platformPath);
2544dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2545dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            push @testsToRun, sort pathcmp @testsFound;
2546dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            @testsFound = ();
2547dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
2548dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            print "test $test not found\n";
2549dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2550dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2551dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2552dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!scalar @ARGV) {
2553dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        @testsFound = ();
2554dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $testDirectory);
2555dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        for my $level (@platformTestHierarchy) {
2556dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $level);
2557dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2558dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        push @testsToRun, sort pathcmp @testsFound;
2559dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        @testsFound = ();
2560dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2561dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # We need to minimize the time when Apache and WebSocketServer is locked by tests
2562dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        # so run them last if no explicit order was specified in the argument list.
2563dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my @httpTests;
2564dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my @websocketTests;
2565dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my @otherTests;
2566dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        foreach my $test (@testsToRun) {
2567dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if ($test =~ /^http\//) {
2568dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push(@httpTests, $test);
2569dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } elsif ($test =~ /^websocket\//) {
2570dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push(@websocketTests, $test);
2571dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            } else {
2572dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                push(@otherTests, $test);
2573dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            }
2574dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2575dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        @testsToRun = (@otherTests, @httpTests, @websocketTests);
2576dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2577dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2578dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Reverse the tests
2579dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    @testsToRun = reverse @testsToRun if $reverseTests;
2580dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2581dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # Shuffle the array
2582dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    @testsToRun = shuffle(@testsToRun) if $randomizeTests;
2583dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2584dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return @testsToRun;
2585dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2586dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2587dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub printResults
2588dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2589dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my %text = (
2590dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        match => "succeeded",
2591dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mismatch => "had incorrect layout",
2592dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        new => "were new",
2593dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        timedout => "timed out",
2594dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        crash => "crashed",
259565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        webProcessCrash => "Web process crashed",
2596dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        error => "had stderr output"
2597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    );
2598dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
259965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    for my $type ("match", "mismatch", "new", "timedout", "crash", "webProcessCrash", "error") {
2600dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $typeCount = $counts{$type};
2601dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        next unless $typeCount;
2602dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $typeText = $text{$type};
2603dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        my $message;
2604dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if ($typeCount == 1) {
2605dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $typeText =~ s/were/was/;
2606dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $message = sprintf "1 test case (%d%%) %s\n", 1 * 100 / $count, $typeText;
2607dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        } else {
2608dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            $message = sprintf "%d test cases (%d%%) %s\n", $typeCount, $typeCount * 100 / $count, $typeText;
2609dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
2610dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        $message =~ s-\(0%\)-(<1%)-;
2611dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        print $message;
2612dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
2613dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2614dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2615dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocksub stopRunningTestsEarlyIfNeeded()
2616dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
2617dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    # --reset-results does not check pass vs. fail, so exitAfterNFailures makes no sense with --reset-results.
2618e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return 0 if $resetResults;
2619dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2620dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    my $passCount = $counts{match} || 0; # $counts{match} will be undefined if we've not yet passed a test (e.g. the first test fails).
26216c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    my $newCount = $counts{new} || 0;
26226c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    my $failureCount = $count - $passCount - $newCount; # "Failure" here includes timeouts, crashes, etc.
2623e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    if ($exitAfterNFailures && $failureCount >= $exitAfterNFailures) {
2624e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        print "\nExiting early after $failureCount failures. $count tests run.";
2625e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        closeDumpTool();
2626e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return 1;
2627e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
2628dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
2629e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    my $crashCount = $counts{crash} || 0;
263081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    my $webProcessCrashCount = $counts{webProcessCrash} || 0;
2631e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    my $timeoutCount = $counts{timedout} || 0;
263281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if ($exitAfterNCrashesOrTimeouts && $crashCount + $webProcessCrashCount + $timeoutCount >= $exitAfterNCrashesOrTimeouts) {
263381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        print "\nExiting early after $crashCount crashes, $webProcessCrashCount web process crashes, and $timeoutCount timeouts. $count tests run.";
2634e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        closeDumpTool();
2635e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return 1;
2636e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    }
2637e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
2638e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return 0;
2639dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
2640f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
26412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block# Store this at global scope so it won't be GCed (and thus unlinked) until the program exits.
26422fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockmy $debuggerTempDirectory;
26432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26442fc2651226baac27029e38c9d6ef883fa32084dbSteve Blocksub createDebuggerCommandFile()
26452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
26462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return unless isCygwin();
26472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my @commands = (
26492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '.logopen /t "' . toWindowsPath($testResultsDirectory) . "\\" . $windowsCrashLogFilePrefix . '.txt"',
26502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '.srcpath "' . toWindowsPath(sourceDir()) . '"',
26512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '!analyze -vv',
26522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '~*kpn',
26532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        'q',
26542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    );
26552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    $debuggerTempDirectory = File::Temp->newdir;
26572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $commandFile = File::Spec->catfile($debuggerTempDirectory, "debugger-commands.txt");
26592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unless (open COMMANDS, '>', $commandFile) {
26602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        print "Failed to open $commandFile. Crash logs will not be saved.\n";
26612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
26622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
26632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    print COMMANDS join("\n", @commands), "\n";
26642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    unless (close COMMANDS) {
26652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        print "Failed to write to $commandFile. Crash logs will not be saved.\n";
26662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
26672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
26682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
26692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return $commandFile;
26702fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
26712fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
267281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochsub readRegistryString($)
267381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
267481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    my ($valueName) = @_;
267581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    chomp(my $string = `regtool --wow32 get "$valueName"`);
267681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return $string;
267781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
267881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
267981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochsub writeRegistryString($$)
268081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
268181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    my ($valueName, $string) = @_;
268281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
268381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    my $error = system "regtool", "--wow32", "set", "-s", $valueName, $string;
268481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
268581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    # On Windows Vista/7 with UAC enabled, regtool will fail to modify the registry, but will still
268681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    # return a successful exit code. So we double-check here that the value we tried to write to the
268781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    # registry was really written.
268881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    return !$error && readRegistryString($valueName) eq $string;
268981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
269081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
2691f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merricksub setUpWindowsCrashLogSaving()
2692f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
2693f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return unless isCygwin();
2694f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2695f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unless (defined $ENV{_NT_SYMBOL_PATH}) {
2696f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        print "The _NT_SYMBOL_PATH environment variable is not set. Crash logs will not be saved.\nSee <http://trac.webkit.org/wiki/BuildingOnWindows#GettingCrashLogs>.\n";
2697f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
2698f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
2699f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2700f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    my $ntsdPath = File::Spec->catfile(toCygwinPath($ENV{PROGRAMFILES}), "Debugging Tools for Windows (x86)", "ntsd.exe");
2701f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    unless (-f $ntsdPath) {
27022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        $ntsdPath = File::Spec->catfile(toCygwinPath($ENV{ProgramW6432}), "Debugging Tools for Windows (x64)", "ntsd.exe");
2703f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        unless (-f $ntsdPath) {
27042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            $ntsdPath = File::Spec->catfile(toCygwinPath($ENV{SYSTEMROOT}), "system32", "ntsd.exe");
27052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            unless (-f $ntsdPath) {
27062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                print STDERR "Can't find ntsd.exe. Crash logs will not be saved.\nSee <http://trac.webkit.org/wiki/BuildingOnWindows#GettingCrashLogs>.\n";
27072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                return;
27082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            }
2709f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        }
2710f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
2711f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
27122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # If we used -c (instead of -cf) we could pass the commands directly on the command line. But
27132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # when the commands include multiple quoted paths (e.g., for .logopen and .srcpath), Windows
27142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # fails to invoke the post-mortem debugger at all (perhaps due to a bug in Windows's command
27152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # line parsing). So we save the commands to a file instead and tell the debugger to execute them
27162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    # using -cf.
27172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my $commandFile = createDebuggerCommandFile() or return;
27182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
27192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    my @options = (
27202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '-p %ld',
27212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '-e %ld',
27222fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '-g',
27232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '-lines',
27242fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        '-cf "' . toWindowsPath($commandFile) . '"',
27252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    );
27262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
2727f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    my %values = (
27282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        Debugger => '"' . toWindowsPath($ntsdPath) . '" ' . join(' ', @options),
2729f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        Auto => 1
2730f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    );
2731f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2732f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    foreach my $value (keys %values) {
273381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        $previousWindowsPostMortemDebuggerValues{$value} = readRegistryString("$windowsPostMortemDebuggerKey/$value");
273481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        next if writeRegistryString("$windowsPostMortemDebuggerKey/$value", $values{$value});
2735f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2736f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        print "Failed to set \"$windowsPostMortemDebuggerKey/$value\". Crash logs will not be saved.\nSee <http://trac.webkit.org/wiki/BuildingOnWindows#GettingCrashLogs>.\n";
2737f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
2738f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
2739f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2740f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    print "Crash logs will be saved to $testResultsDirectory.\n";
2741f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
2742f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2743f486d19d62f1bc33246748b14b14a9dfa617b57fIain MerrickEND {
2744f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return unless isCygwin();
2745f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
2746f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    foreach my $value (keys %previousWindowsPostMortemDebuggerValues) {
274781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        next if writeRegistryString("$windowsPostMortemDebuggerKey/$value", $previousWindowsPostMortemDebuggerValues{$value});
274881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        print "Failed to restore \"$windowsPostMortemDebuggerKey/$value\" to its previous value \"$previousWindowsPostMortemDebuggerValues{$value}\"\n.";
2749f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
2750f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
2751