summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/run-webkit-tests
diff options
context:
space:
mode:
Diffstat (limited to 'WebKitTools/Scripts/run-webkit-tests')
-rwxr-xr-xWebKitTools/Scripts/run-webkit-tests665
1 files changed, 377 insertions, 288 deletions
diff --git a/WebKitTools/Scripts/run-webkit-tests b/WebKitTools/Scripts/run-webkit-tests
index f51cf53..a08a53c 100755
--- a/WebKitTools/Scripts/run-webkit-tests
+++ b/WebKitTools/Scripts/run-webkit-tests
@@ -5,6 +5,7 @@
# Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com)
# Copyright (C) 2007 Eric Seidel <eric@webkit.org>
# Copyright (C) 2009 Google Inc. All rights reserved.
+# Copyright (C) 2009 Andras Becsi (becsi.andras@stud.u-szeged.hu), University of Szeged
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -70,80 +71,86 @@ use webkitdirs;
use VCSUtils;
use POSIX;
-sub launchWithCurrentEnv(@);
-sub openDiffTool();
-sub openDumpTool();
+sub buildPlatformResultHierarchy();
+sub buildPlatformTestHierarchy(@);
+sub closeCygpaths();
sub closeDumpTool();
-sub dumpToolDidCrash();
sub closeHTTPD();
sub countAndPrintLeaks($$$);
+sub countFinishedTest($$$$);
+sub deleteExpectedAndActualResults($);
+sub dumpToolDidCrash();
+sub epiloguesAndPrologues($$);
+sub expectedDirectoryForTest($;$;$);
sub fileNameWithNumber($$);
+sub htmlForResultsSection(\@$&);
+sub isTextOnlyTest($);
+sub launchWithCurrentEnv(@);
sub numericcmp($$);
+sub openDiffTool();
+sub openDumpTool();
sub openHTTPDIfNeeded();
+sub parseLeaksandPrintUniqueLeaks();
sub pathcmp($$);
+sub printFailureMessageForTest($$);
sub processIgnoreTests($$);
+sub readFromDumpToolWithTimer(**);
+sub recordActualResultsAndDiff($$);
+sub sampleDumpTool();
+sub setFileHandleNonBlocking(*$);
sub slowestcmp($$);
sub splitpath($);
sub stripExtension($);
-sub isTextOnlyTest($);
-sub expectedDirectoryForTest($;$;$);
-sub countFinishedTest($$$$);
+sub stripMetrics($$);
sub testCrashedOrTimedOut($$$$$);
-sub sampleDumpTool();
-sub printFailureMessageForTest($$);
sub toURL($);
sub toWindowsPath($);
-sub closeCygpaths();
sub validateSkippedArg($$;$);
-sub htmlForResultsSection(\@$&);
-sub deleteExpectedAndActualResults($);
-sub recordActualResultsAndDiff($$);
-sub buildPlatformResultHierarchy();
-sub buildPlatformTestHierarchy(@);
-sub epiloguesAndPrologues($$);
-sub parseLeaksandPrintUniqueLeaks();
-sub readFromDumpToolWithTimer(*;$);
-sub setFileHandleNonBlocking(*$);
sub writeToFile($$);
# Argument handling
my $addPlatformExceptions = 0;
my $complexText = 0;
+my $exitAfterNFailures = 0;
+my $generateNewResults = isAppleMacWebKit() ? 1 : 0;
my $guardMalloc = '';
my $httpdPort = 8000;
my $httpdSSLPort = 8443;
+my $ignoreMetrics = 0;
my $ignoreTests = '';
+my $iterations = 1;
my $launchSafari = 1;
-my $platform;
+my $mergeDepth;
my $pixelTests = '';
+my $platform;
my $quiet = '';
+my $randomizeTests = 0;
+my $repeatEach = 1;
my $report10Slowest = 0;
my $resetResults = 0;
+my $reverseTests = 0;
+my $root;
+my $runSample = 1;
my $shouldCheckLeaks = 0;
my $showHelp = 0;
-my $testsPerDumpTool;
+my $stripEditingCallbacks = isCygwin();
my $testHTTP = 1;
my $testMedia = 1;
my $testResultsDirectory = "/tmp/layout-test-results";
+my $testsPerDumpTool = 1000;
my $threaded = 0;
+# DumpRenderTree has an internal timeout of 15 seconds, so this must be > 15.
+my $timeoutSeconds = 20;
my $tolerance = 0;
my $treatSkipped = "default";
-my $verbose = 0;
-my $useValgrind = 0;
-my $strictTesting = 0;
-my $generateNewResults = isAppleMacWebKit() ? 1 : 0;
-my $stripEditingCallbacks = isCygwin();
-my $runSample = 1;
-my $root;
-my $reverseTests = 0;
-my $randomizeTests = 0;
-my $mergeDepth;
-my $timeoutSeconds = 15;
my $useRemoteLinksToTests = 0;
+my $useValgrind = 0;
+my $verbose = 0;
+
my @leaksFilenames;
-# Default to --no-http for Qt, and wx for now.
-$testHTTP = 0 if (isQt() || isWx());
+# Default to --no-http for wx for now.
+$testHTTP = 0 if (isWx());
my $expectedTag = "expected";
my $actualTag = "actual";
@@ -167,7 +174,15 @@ if (isAppleMacWebKit()) {
$platform = "mac";
}
} elsif (isQt()) {
- $platform = "qt";
+ if (isDarwin()) {
+ $platform = "qt-mac";
+ } elsif (isLinux()) {
+ $platform = "qt-linux";
+ } elsif (isWindows() || isCygwin()) {
+ $platform = "qt-win";
+ } else {
+ $platform = "qt";
+ }
} elsif (isGtk()) {
$platform = "gtk";
} elsif (isWx()) {
@@ -186,19 +201,21 @@ my $launchSafariDefault = $launchSafari ? "launch" : "do not launch";
my $httpDefault = $testHTTP ? "run" : "do not run";
my $sampleDefault = $runSample ? "run" : "do not run";
-# FIXME: "--strict" should be renamed to qt-mac-comparison, or something along those lines.
my $usage = <<EOF;
Usage: $programName [options] [testdir|testpath ...]
--add-platform-exceptions Put new results for non-platform-specific failing tests into the platform-specific results directory
--complex-text Use the complex text code path for all text (Mac OS X and Windows only)
-c|--configuration config Set DumpRenderTree build configuration
-g|--guard-malloc Enable malloc guard
- --help Show this help message
+ --exit-after-n-failures N Exit after the first N failures instead of running all tests
+ -h|--help Show this help message
--[no-]http Run (or do not run) http tests (default: $httpDefault)
-i|--ignore-tests Comma-separated list of directories or tests to ignore
+ --iterations n Number of times to run the set of tests (e.g. ABCABCABC)
--[no-]launch-safari Launch (or do not launch) Safari to display test results (default: $launchSafariDefault)
-l|--leaks Enable leaks checking
--[no-]new-test-results Generate results for new tests
+ --nthly n Restart DumpRenderTree every n tests (default: $testsPerDumpTool)
-p|--pixel-tests Enable pixel tests
--tolerance t Ignore image differences less than this percentage (default: $tolerance)
--platform Override the detected platform to use for tests and results (default: $platform)
@@ -207,16 +224,17 @@ Usage: $programName [options] [testdir|testpath ...]
--reset-results Reset ALL results (including pixel tests if --pixel-tests is set)
-o|--results-directory Output results directory (default: $testResultsDirectory)
--random Run the tests in a random order
+ --repeat-each n Number of times to run each test (e.g. AAABBBCCC)
--reverse Run the tests in reverse alphabetical order
--root Path to root tools build
--[no-]sample-on-timeout Run sample on timeout (default: $sampleDefault) (Mac OS X only)
- -1|--singly Isolate each test case run (implies --verbose)
+ -1|--singly Isolate each test case run (implies --nthly 1 --verbose)
--skipped=[default|ignore|only] Specifies how to treat the Skipped file
default: Tests/directories listed in the Skipped file are not tested
ignore: The Skipped file is ignored
only: Only those tests/directories listed in the Skipped file will be run
--slowest Report the 10 slowest tests
- --strict Do a comparison with the output on Mac (Qt only)
+ --ignore-metrics Ignore metrics in tests
--[no-]strip-editing-callbacks Remove editing callbacks from expected results
-t|--threaded Run a concurrent JavaScript thead with each test
--timeout t Sets the number of seconds before a test times out (default: $timeoutSeconds)
@@ -229,38 +247,41 @@ EOF
setConfiguration();
my $getOptionsResult = GetOptions(
+ 'add-platform-exceptions' => \$addPlatformExceptions,
'complex-text' => \$complexText,
+ 'exit-after-n-failures=i' => \$exitAfterNFailures,
'guard-malloc|g' => \$guardMalloc,
- 'help' => \$showHelp,
+ 'help|h' => \$showHelp,
'http!' => \$testHTTP,
+ 'ignore-metrics!' => \$ignoreMetrics,
'ignore-tests|i=s' => \$ignoreTests,
+ 'iterations=i' => \$iterations,
'launch-safari!' => \$launchSafari,
'leaks|l' => \$shouldCheckLeaks,
+ 'merge-leak-depth|m:5' => \$mergeDepth,
+ 'new-test-results!' => \$generateNewResults,
+ 'nthly=i' => \$testsPerDumpTool,
'pixel-tests|p' => \$pixelTests,
'platform=s' => \$platform,
'port=i' => \$httpdPort,
'quiet|q' => \$quiet,
+ 'random' => \$randomizeTests,
+ 'repeat-each=i' => \$repeatEach,
'reset-results' => \$resetResults,
- 'new-test-results!' => \$generateNewResults,
'results-directory|o=s' => \$testResultsDirectory,
+ 'reverse' => \$reverseTests,
+ 'root=s' => \$root,
+ 'sample-on-timeout!' => \$runSample,
'singly|1' => sub { $testsPerDumpTool = 1; },
- 'nthly=i' => \$testsPerDumpTool,
'skipped=s' => \&validateSkippedArg,
'slowest' => \$report10Slowest,
- 'threaded|t' => \$threaded,
- 'tolerance=f' => \$tolerance,
- 'verbose|v' => \$verbose,
- 'valgrind' => \$useValgrind,
- 'sample-on-timeout!' => \$runSample,
- 'strict' => \$strictTesting,
'strip-editing-callbacks!' => \$stripEditingCallbacks,
- 'random' => \$randomizeTests,
- 'reverse' => \$reverseTests,
- 'root=s' => \$root,
- 'add-platform-exceptions' => \$addPlatformExceptions,
- 'merge-leak-depth|m:5' => \$mergeDepth,
+ 'threaded|t' => \$threaded,
'timeout=i' => \$timeoutSeconds,
+ 'tolerance=f' => \$tolerance,
'use-remote-links-to-tests' => \$useRemoteLinksToTests,
+ 'valgrind' => \$useValgrind,
+ 'verbose|v' => \$verbose,
);
if (!$getOptionsResult || $showHelp) {
@@ -275,8 +296,6 @@ my $skippedOnly = $treatSkipped eq "only";
my $configuration = configuration();
-$testsPerDumpTool = 1000 if !$testsPerDumpTool;
-
$verbose = 1 if $testsPerDumpTool == 1;
if ($shouldCheckLeaks && $testsPerDumpTool > 1000) {
@@ -286,8 +305,8 @@ if ($shouldCheckLeaks && $testsPerDumpTool > 1000) {
# Stack logging does not play well with QuickTime on Tiger (rdar://problem/5537157)
$testMedia = 0 if $shouldCheckLeaks && isTiger();
-# Generating remote links causes a lot of unnecessary spew on GTK and Qt build bot
-$useRemoteLinksToTests = 0 if (isGtk() || isQt());
+# Generating remote links causes a lot of unnecessary spew on GTK build bot
+$useRemoteLinksToTests = 0 if isGtk();
setConfigurationProductDir(Cwd::abs_path($root)) if (defined($root));
my $productDir = productDir();
@@ -297,10 +316,30 @@ $productDir .= "/Programs" if isGtk();
chdirWebKit();
if (!defined($root)) {
- # Push the parameters to build-dumprendertree as an array
+ print STDERR "Running build-dumprendertree\n";
+
+ local *DEVNULL;
+ my ($childIn, $childOut, $childErr);
+ if ($quiet) {
+ open(DEVNULL, ">", File::Spec->devnull) or die "Failed to open /dev/null";
+ $childOut = ">&DEVNULL";
+ $childErr = ">&DEVNULL";
+ } else {
+ # When not quiet, let the child use our stdout/stderr.
+ $childOut = ">&STDOUT";
+ $childErr = ">&STDERR";
+ }
+
my @args = argumentsForConfiguration();
+ my $buildProcess = open3($childIn, $childOut, $childErr, "WebKitTools/Scripts/build-dumprendertree", @args) or die "Failed to run build-dumprendertree";
+ close($childIn);
+ waitpid $buildProcess, 0;
+ my $buildResult = $?;
+ close($childOut);
+ close($childErr);
+
+ close DEVNULL if ($quiet);
- my $buildResult = system "WebKitTools/Scripts/build-dumprendertree", @args;
if ($buildResult) {
print STDERR "Compiling DumpRenderTree failed!\n";
exit exitStatus($buildResult);
@@ -320,7 +359,7 @@ checkFrameworks() unless isCygwin();
if (isAppleMacWebKit()) {
push @INC, $productDir;
- eval 'use DumpRenderTreeSupport;';
+ require DumpRenderTreeSupport;
}
my $layoutTestsName = "LayoutTests";
@@ -351,16 +390,17 @@ if ($pixelTests) {
}
}
-my @tests = ();
-my %testType = ();
-
system "ln", "-s", $testDirectory, "/tmp/LayoutTests" unless -x "/tmp/LayoutTests";
-my %ignoredFiles = ();
+my %ignoredFiles = ( "results.html" => 1 );
my %ignoredDirectories = map { $_ => 1 } qw(platform);
-my %ignoredLocalDirectories = map { $_ => 1 } qw(.svn _svn resources);
+my %ignoredLocalDirectories = map { $_ => 1 } qw(.svn _svn resources script-tests);
my %supportedFileExtensions = map { $_ => 1 } qw(html shtml xml xhtml pl php);
+if (!checkWebCoreMathMLSupport(0)) {
+ $ignoredDirectories{'mathml'} = 1;
+}
+
# FIXME: We should fix webkitdirs.pm:hasSVG/WMLSupport() to do the correct feature detection for Cygwin.
if (checkWebCoreSVGSupport(0)) {
$supportedFileExtensions{'svg'} = 1;
@@ -388,6 +428,10 @@ if (!checkWebCore3DRenderingSupport(0)) {
$ignoredDirectories{'transforms/3d'} = 1;
}
+if (!checkWebCore3DCanvasSupport(0)) {
+ $ignoredDirectories{'fast/canvas/webgl'} = 1;
+}
+
if (checkWebCoreWMLSupport(0)) {
$supportedFileExtensions{'wml'} = 1;
} else {
@@ -404,105 +448,13 @@ if (!checkWebCoreWCSSSupport(0)) {
$ignoredDirectories{'fast/wcss'} = 1;
}
-if ($ignoreTests) {
- processIgnoreTests($ignoreTests, "ignore-tests");
-}
-
-sub fileShouldBeIgnored {
- my($filePath) = @_;
- foreach my $ignoredDir (keys %ignoredDirectories) {
- if ($filePath =~ m/^$ignoredDir/) {
- return 1;
- }
- }
- return 0;
-}
-
-if (!$ignoreSkipped) {
- foreach my $level (@platformTestHierarchy) {
- if (open SKIPPED, "<", "$level/Skipped") {
- if ($verbose) {
- my ($dir, $name) = splitpath($level);
- print "Skipped tests in $name:\n";
- }
-
- while (<SKIPPED>) {
- my $skipped = $_;
- chomp $skipped;
- $skipped =~ s/^[ \n\r]+//;
- $skipped =~ s/[ \n\r]+$//;
- if ($skipped && $skipped !~ /^#/) {
- if ($skippedOnly) {
- if (!&fileShouldBeIgnored($skipped)) {
- push(@ARGV, $skipped);
- } elsif ($verbose) {
- print " $skipped\n";
- }
- } else {
- if ($verbose) {
- print " $skipped\n";
- }
- processIgnoreTests($skipped, "Skipped");
- }
- }
- }
- close SKIPPED;
- }
- }
-}
-
+processIgnoreTests($ignoreTests, "ignore-tests") if $ignoreTests;
+readSkippedFiles() unless $ignoreSkipped;
-my $directoryFilter = sub {
- return () if exists $ignoredLocalDirectories{basename($File::Find::dir)};
- return () if exists $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)};
- return @_;
-};
-
-my $fileFilter = sub {
- my $filename = $_;
- if ($filename =~ /\.([^.]+)$/) {
- if (exists $supportedFileExtensions{$1}) {
- my $path = File::Spec->abs2rel(catfile($File::Find::dir, $filename), $testDirectory);
- push @tests, $path if !exists $ignoredFiles{$path};
- }
- }
-};
-
-for my $test (@ARGV) {
- $test =~ s/^($layoutTestsName|$testDirectory)\///;
- my $fullPath = catfile($testDirectory, $test);
- if (file_name_is_absolute($test)) {
- print "can't run test $test outside $testDirectory\n";
- } elsif (-f $fullPath) {
- my ($filename, $pathname, $fileExtension) = fileparse($test, qr{\.[^.]+$});
- if (!exists $supportedFileExtensions{substr($fileExtension, 1)}) {
- print "test $test does not have a supported extension\n";
- } elsif ($testHTTP || $pathname !~ /^http\//) {
- push @tests, $test;
- }
- } elsif (-d $fullPath) {
- find({ preprocess => $directoryFilter, wanted => $fileFilter }, $fullPath);
-
- for my $level (@platformTestHierarchy) {
- my $platformPath = catfile($level, $test);
- find({ preprocess => $directoryFilter, wanted => $fileFilter }, $platformPath) if (-d $platformPath);
- }
- } else {
- print "test $test not found\n";
- }
-}
-if (!scalar @ARGV) {
- find({ preprocess => $directoryFilter, wanted => $fileFilter }, $testDirectory);
-
- for my $level (@platformTestHierarchy) {
- find({ preprocess => $directoryFilter, wanted => $fileFilter }, $level);
- }
-}
+my @tests = findTestsToRun();
die "no tests to run\n" if !@tests;
-@tests = sort pathcmp @tests;
-
my %counts;
my %tests;
my %imagesPresent;
@@ -537,20 +489,31 @@ my $isHttpdOpen = 0;
sub catch_pipe { $dumpToolCrashed = 1; }
$SIG{"PIPE"} = "catch_pipe";
-print "Testing ", scalar @tests, " test cases.\n";
+print "Testing ", scalar @tests, " test cases";
+print " $iterations times" if ($iterations > 1);
+print ", repeating each test $repeatEach times" if ($repeatEach > 1);
+print ".\n";
+
my $overallStartTime = time;
my %expectedResultPaths;
-# Reverse the tests
-@tests = reverse @tests if $reverseTests;
-
-# Shuffle the array
-@tests = shuffle(@tests) if $randomizeTests;
+my @originalTests = @tests;
+# Add individual test repetitions
+if ($repeatEach > 1) {
+ @tests = ();
+ foreach my $test (@originalTests) {
+ for (my $i = 0; $i < $repeatEach; $i++) {
+ push(@tests, $test);
+ }
+ }
+}
+# Add test set repetitions
+for (my $i = 1; $i < $iterations; $i++) {
+ push(@tests, @originalTests);
+}
for my $test (@tests) {
- next if $test eq 'results.html';
-
my $newDumpTool = not $isDumpToolOpen;
openDumpTool();
@@ -648,14 +611,12 @@ for my $test (@tests) {
# The first block is the output of the test (in text, RenderTree or other formats).
# The second block is for optional pixel data in PNG format, and may be empty if
# pixel tests are not being run, or the test does not dump pixels (e.g. text tests).
-
- my $actualRead = readFromDumpToolWithTimer(IN);
- my $errorRead = readFromDumpToolWithTimer(ERROR, $actualRead->{status} eq "timedOut");
+ my $readResults = readFromDumpToolWithTimer(IN, ERROR);
- my $actual = $actualRead->{output};
- my $error = $errorRead->{output};
+ my $actual = $readResults->{output};
+ my $error = $readResults->{error};
- $expectedExtension = $actualRead->{extension};
+ $expectedExtension = $readResults->{extension};
my $expectedFileName = "$base-$expectedTag.$expectedExtension";
my $isText = isTextOnlyTest($actual);
@@ -663,12 +624,12 @@ for my $test (@tests) {
my $expectedDir = expectedDirectoryForTest($base, $isText, $expectedExtension);
$expectedResultPaths{$base} = "$expectedDir/$expectedFileName";
- unless ($actualRead->{status} eq "success" && $errorRead->{status} eq "success") {
- my $crashed = $actualRead->{status} eq "crashed" || $errorRead->{status} eq "crashed";
+ unless ($readResults->{status} eq "success") {
+ my $crashed = $readResults->{status} eq "crashed";
testCrashedOrTimedOut($test, $base, $crashed, $actual, $error);
countFinishedTest($test, $base, $crashed ? "crash" : "timedout", 0);
next;
- }
+ }
$durations{$test} = time - $startTime if $report10Slowest;
@@ -682,15 +643,9 @@ for my $test (@tests) {
}
close EXPECTED;
}
- my $expectedMac;
- if (!isAppleMacWebKit() && $strictTesting && !$isText) {
- if (!$resetResults && open EXPECTED, "<", "$testDirectory/platform/mac/$expectedFileName") {
- $expectedMac = "";
- while (<EXPECTED>) {
- $expectedMac .= $_;
- }
- close EXPECTED;
- }
+
+ if ($ignoreMetrics && !$isText && defined $expected) {
+ ($actual, $expected) = stripMetrics($actual, $expected);
}
if ($shouldCheckLeaks && $testsPerDumpTool == 1) {
@@ -776,57 +731,6 @@ for my $test (@tests) {
}
}
- if (!isAppleMacWebKit() && $strictTesting && !$isText) {
- if (defined $expectedMac) {
- my $simplified_actual;
- $simplified_actual = $actual;
- $simplified_actual =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g;
- $simplified_actual =~ s/size -?[0-9]+x-?[0-9]+ *//g;
- $simplified_actual =~ s/text run width -?[0-9]+: //g;
- $simplified_actual =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g;
- $simplified_actual =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g;
- $simplified_actual =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g;
- $simplified_actual =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g;
- $simplified_actual =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g;
- $simplified_actual =~ s/\([0-9]+px/px/g;
- $simplified_actual =~ s/ *" *\n +" */ /g;
- $simplified_actual =~ s/" +$/"/g;
-
- $simplified_actual =~ s/- /-/g;
- $simplified_actual =~ s/\n( *)"\s+/\n$1"/g;
- $simplified_actual =~ s/\s+"\n/"\n/g;
-
- $expectedMac =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g;
- $expectedMac =~ s/size -?[0-9]+x-?[0-9]+ *//g;
- $expectedMac =~ s/text run width -?[0-9]+: //g;
- $expectedMac =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g;
- $expectedMac =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g;
- $expectedMac =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g;
- $expectedMac =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g;
- $expectedMac =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g;
- $expectedMac =~ s/\([0-9]+px/px/g;
- $expectedMac =~ s/ *" *\n +" */ /g;
- $expectedMac =~ s/" +$/"/g;
-
- $expectedMac =~ s/- /-/g;
- $expectedMac =~ s/\n( *)"\s+/\n$1"/g;
- $expectedMac =~ s/\s+"\n/"\n/g;
-
- if ($simplified_actual ne $expectedMac) {
- writeToFile("/tmp/actual.txt", $simplified_actual);
- writeToFile("/tmp/expected.txt", $expectedMac);
- system "diff -u \"/tmp/expected.txt\" \"/tmp/actual.txt\" > \"/tmp/simplified.diff\"";
-
- $diffResult = "failed";
- if ($verbose) {
- print "\n";
- system "cat /tmp/simplified.diff";
- print "failed!!!!!";
- }
- }
- }
- }
-
if (dumpToolDidCrash()) {
$result = "crash";
testCrashedOrTimedOut($test, $base, 1, $actual, $error);
@@ -971,6 +875,17 @@ for my $test (@tests) {
}
countFinishedTest($test, $base, $result, $isText);
+
+ # --reset-results does not check pass vs. fail, so exitAfterNFailures makes no sense with --reset-results.
+ if ($exitAfterNFailures && !$resetResults) {
+ my $passCount = $counts{match} || 0; # $counts{match} will be undefined if we've not yet passed a test (e.g. the first test fails).
+ my $failureCount = $count - $passCount; # "Failure" here includes new tests, timeouts, crashes, etc.
+ if ($failureCount >= $exitAfterNFailures) {
+ print "\nExiting early after $failureCount failures. $count tests run.";
+ closeDumpTool();
+ last;
+ }
+ }
}
printf "\n%0.2fs total testing time\n", (time - $overallStartTime) . "";
@@ -990,8 +905,7 @@ if ($isDiffToolOpen && $shouldCheckLeaks) {
if ($totalLeaks) {
if ($mergeDepth) {
parseLeaksandPrintUniqueLeaks();
- }
- else {
+ } else {
print "\nWARNING: $totalLeaks total leaks found!\n";
print "See above for individual leaks results.\n" if ($leaksOutputFileNumber > 2);
}
@@ -1025,31 +939,7 @@ if ($resetResults || ($counts{match} && $counts{match} == $count)) {
exit;
}
-
-my %text = (
- match => "succeeded",
- mismatch => "had incorrect layout",
- new => "were new",
- timedout => "timed out",
- crash => "crashed",
- error => "had stderr output"
-);
-
-for my $type ("match", "mismatch", "new", "timedout", "crash", "error") {
- my $c = $counts{$type};
- if ($c) {
- my $t = $text{$type};
- my $message;
- if ($c == 1) {
- $t =~ s/were/was/;
- $message = sprintf "1 test case (%d%%) %s\n", 1 * 100 / $count, $t;
- } else {
- $message = sprintf "%d test cases (%d%%) %s\n", $c, $c * 100 / $count, $t;
- }
- $message =~ s-\(0%\)-(<1%)-;
- print $message;
- }
-}
+printResults();
mkpath $testResultsDirectory;
@@ -1060,6 +950,10 @@ print HTML "<title>Layout Test Results</title>\n";
print HTML "</head>\n";
print HTML "<body>\n";
+if ($ignoreMetrics) {
+ print HTML "<h4>Tested with metrics ignored.</h4>";
+}
+
print HTML htmlForResultsSection(@{$tests{mismatch}}, "Tests where results did not match expected results", \&linksForMismatchTest);
print HTML htmlForResultsSection(@{$tests{timedout}}, "Tests that timed out", \&linksForErrorTest);
print HTML htmlForResultsSection(@{$tests{crash}}, "Tests that caused the DumpRenderTree tool to crash", \&linksForErrorTest);
@@ -1143,6 +1037,13 @@ sub countAndPrintLeaks($$$)
);
}
+ if (isSnowLeopard()) {
+ push @callStacksToExclude, (
+ "readMakerNoteProps", # <rdar://problem/7156432> leak in ImageIO
+ "QTKitMovieControllerView completeUISetup", # <rdar://problem/7155156> leak in QTKit
+ );
+ }
+
my $leaksTool = sourceDir() . "/WebKitTools/Scripts/run-leaks";
my $excludeString = "--exclude-callstack '" . (join "' --exclude-callstack '", @callStacksToExclude) . "'";
$excludeString .= " --exclude-type '" . (join "' --exclude-type '", @typesToExclude) . "'" if @typesToExclude;
@@ -1172,7 +1073,7 @@ sub countAndPrintLeaks($$$)
writeToFile($leaksFilePath, $leaksOutput);
- push( @leaksFilenames, $leaksFilePath );
+ push @leaksFilenames, $leaksFilePath;
}
return $adjustedCount;
@@ -1414,6 +1315,9 @@ sub openHTTPDIfNeeded()
} elsif (isDebianBased()) {
$httpdPath = "/usr/sbin/apache2";
$httpdConfig = "$testDirectory/http/conf/apache2-debian-httpd.conf";
+ } elsif (isFedoraBased()) {
+ $httpdPath = "/usr/sbin/httpd";
+ $httpdConfig = "$testDirectory/http/conf/fedora-httpd.conf";
} else {
$httpdConfig = "$testDirectory/http/conf/httpd.conf";
$httpdConfig = "$testDirectory/http/conf/apache2-httpd.conf" if `$httpdPath -v` =~ m|Apache/2|;
@@ -1476,7 +1380,8 @@ sub fileNameWithNumber($$)
return $base;
}
-sub processIgnoreTests($$) {
+sub processIgnoreTests($$)
+{
my @ignoreList = split(/\s*,\s*/, shift);
my $listName = shift;
@@ -1541,7 +1446,8 @@ sub expectedDirectoryForTest($;$;$)
return $isText ? $expectedDirectory : $platformResultHierarchy[$#platformResultHierarchy];
}
-sub countFinishedTest($$$$) {
+sub countFinishedTest($$$$)
+{
my ($test, $base, $result, $isText) = @_;
if (($count + 1) % $testsPerDumpTool == 0 || $count == $#tests) {
@@ -1563,7 +1469,6 @@ sub countFinishedTest($$$$) {
$count++;
$counts{$result}++;
push @{$tests{$result}}, $test;
- $testType{$test} = $isText;
}
sub testCrashedOrTimedOut($$$$$)
@@ -1833,6 +1738,9 @@ sub buildPlatformResultHierarchy()
for (; $i < @macPlatforms; $i++) {
push @platforms, $macPlatforms[$i];
}
+ } elsif ($platform =~ /^qt-/) {
+ push @platforms, $platform;
+ push @platforms, "qt";
} else {
@platforms = $platform;
}
@@ -1854,7 +1762,8 @@ sub buildPlatformTestHierarchy(@)
return ($platformHierarchy[0], $platformHierarchy[$#platformHierarchy]);
}
-sub epiloguesAndPrologues($$) {
+sub epiloguesAndPrologues($$)
+{
my ($lastDirectory, $directory) = @_;
my @lastComponents = split('/', $lastDirectory);
my @components = split('/', $directory);
@@ -1890,7 +1799,8 @@ sub epiloguesAndPrologues($$) {
return @result;
}
-sub parseLeaksandPrintUniqueLeaks() {
+sub parseLeaksandPrintUniqueLeaks()
+{
return unless @leaksFilenames;
my $mergedFilenames = join " ", @leaksFilenames;
@@ -1926,11 +1836,12 @@ sub extensionForMimeType($)
}
# Read up to the first #EOF (the content block of the test), or until detecting crashes or timeouts.
-sub readFromDumpToolWithTimer(*;$)
+sub readFromDumpToolWithTimer(**)
{
- my ($fh, $dontWaitForTimeOut) = @_;
+ my ($fhIn, $fhError) = @_;
- setFileHandleNonBlocking($fh, 1);
+ setFileHandleNonBlocking($fhIn, 1);
+ setFileHandleNonBlocking($fhError, 1);
my $maximumSecondsWithoutOutput = $timeoutSeconds;
$maximumSecondsWithoutOutput *= 10 if $guardMalloc;
@@ -1939,11 +1850,14 @@ sub readFromDumpToolWithTimer(*;$)
my $timeOfLastSuccessfulRead = time;
my @output = ();
+ my @error = ();
my $status = "success";
my $mimeType = "text/plain";
# We don't have a very good way to know when the "headers" stop
# and the content starts, so we use this as a hack:
my $haveSeenContentType = 0;
+ my $haveSeenEofIn = 0;
+ my $haveSeenEofError = 0;
while (1) {
if (time - $timeOfLastSuccessfulRead > $maximumSecondsWithoutOutput) {
@@ -1951,37 +1865,48 @@ sub readFromDumpToolWithTimer(*;$)
last;
}
- my $line = readline($fh);
- if (!defined($line)) {
+ # Once we've seen the EOF, we must not read anymore.
+ my $lineIn = readline($fhIn) unless $haveSeenEofIn;
+ my $lineError = readline($fhError) unless $haveSeenEofError;
+ if (!defined($lineIn) && !defined($lineError)) {
+ last if ($haveSeenEofIn && $haveSeenEofError);
+
if ($! != EAGAIN) {
$status = "crashed";
last;
}
- if ($dontWaitForTimeOut) {
- last;
- }
-
# No data ready
usleep($microsecondsToWaitBeforeReadingAgain);
next;
}
$timeOfLastSuccessfulRead = time;
-
- if (!$haveSeenContentType && $line =~ /^Content-Type: (\S+)$/) {
- $mimeType = $1;
- $haveSeenContentType = 1;
- next;
+
+ if (defined($lineIn)) {
+ if (!$haveSeenContentType && $lineIn =~ /^Content-Type: (\S+)$/) {
+ $mimeType = $1;
+ $haveSeenContentType = 1;
+ } elsif ($lineIn =~ /#EOF/) {
+ $haveSeenEofIn = 1;
+ } else {
+ push @output, $lineIn;
+ }
+ }
+ if (defined($lineError)) {
+ if ($lineError =~ /#EOF/) {
+ $haveSeenEofError = 1;
+ } else {
+ push @error, $lineError;
+ }
}
- last if ($line =~ /#EOF/);
-
- push @output, $line;
}
- setFileHandleNonBlocking($fh, 0);
+ setFileHandleNonBlocking($fhIn, 0);
+ setFileHandleNonBlocking($fhError, 0);
return {
output => join("", @output),
+ error => join("", @error),
status => $status,
mimeType => $mimeType,
extension => extensionForMimeType($mimeType)
@@ -2016,3 +1941,167 @@ sub sampleDumpTool()
my $outputFile = "$outputDirectory/HangReport.txt";
system "/usr/bin/sample", $dumpToolPID, qw(10 10 -file), $outputFile;
}
+
+sub stripMetrics($$)
+{
+ my ($actual, $expected) = @_;
+
+ foreach my $result ($actual, $expected) {
+ $result =~ s/at \(-?[0-9]+,-?[0-9]+\) *//g;
+ $result =~ s/size -?[0-9]+x-?[0-9]+ *//g;
+ $result =~ s/text run width -?[0-9]+: //g;
+ $result =~ s/text run width -?[0-9]+ [a-zA-Z ]+: //g;
+ $result =~ s/RenderButton {BUTTON} .*/RenderButton {BUTTON}/g;
+ $result =~ s/RenderImage {INPUT} .*/RenderImage {INPUT}/g;
+ $result =~ s/RenderBlock {INPUT} .*/RenderBlock {INPUT}/g;
+ $result =~ s/RenderTextControl {INPUT} .*/RenderTextControl {INPUT}/g;
+ $result =~ s/\([0-9]+px/px/g;
+ $result =~ s/ *" *\n +" */ /g;
+ $result =~ s/" +$/"/g;
+
+ $result =~ s/- /-/g;
+ $result =~ s/\n( *)"\s+/\n$1"/g;
+ $result =~ s/\s+"\n/"\n/g;
+ $result =~ s/scrollWidth [0-9]+/scrollWidth/g;
+ $result =~ s/scrollHeight [0-9]+/scrollHeight/g;
+ }
+
+ return ($actual, $expected);
+}
+
+sub fileShouldBeIgnored
+{
+ my ($filePath) = @_;
+ foreach my $ignoredDir (keys %ignoredDirectories) {
+ if ($filePath =~ m/^$ignoredDir/) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub readSkippedFiles
+{
+ foreach my $level (@platformTestHierarchy) {
+ if (open SKIPPED, "<", "$level/Skipped") {
+ if ($verbose) {
+ my ($dir, $name) = splitpath($level);
+ print "Skipped tests in $name:\n";
+ }
+
+ while (<SKIPPED>) {
+ my $skipped = $_;
+ chomp $skipped;
+ $skipped =~ s/^[ \n\r]+//;
+ $skipped =~ s/[ \n\r]+$//;
+ if ($skipped && $skipped !~ /^#/) {
+ if ($skippedOnly) {
+ if (!&fileShouldBeIgnored($skipped)) {
+ push(@ARGV, $skipped);
+ } elsif ($verbose) {
+ print " $skipped\n";
+ }
+ } else {
+ if ($verbose) {
+ print " $skipped\n";
+ }
+ processIgnoreTests($skipped, "Skipped");
+ }
+ }
+ }
+ close SKIPPED;
+ }
+ }
+}
+
+my @testsToRun;
+
+sub directoryFilter
+{
+ return () if exists $ignoredLocalDirectories{basename($File::Find::dir)};
+ return () if exists $ignoredDirectories{File::Spec->abs2rel($File::Find::dir, $testDirectory)};
+ return @_;
+}
+
+sub fileFilter
+{
+ my $filename = $_;
+ if ($filename =~ /\.([^.]+)$/) {
+ if (exists $supportedFileExtensions{$1}) {
+ my $path = File::Spec->abs2rel(catfile($File::Find::dir, $filename), $testDirectory);
+ push @testsToRun, $path if !exists $ignoredFiles{$path};
+ }
+ }
+}
+
+sub findTestsToRun
+{
+ @testsToRun = ();
+
+ for my $test (@ARGV) {
+ $test =~ s/^($layoutTestsName|$testDirectory)\///;
+ my $fullPath = catfile($testDirectory, $test);
+ if (file_name_is_absolute($test)) {
+ print "can't run test $test outside $testDirectory\n";
+ } elsif (-f $fullPath) {
+ my ($filename, $pathname, $fileExtension) = fileparse($test, qr{\.[^.]+$});
+ if (!exists $supportedFileExtensions{substr($fileExtension, 1)}) {
+ print "test $test does not have a supported extension\n";
+ } elsif ($testHTTP || $pathname !~ /^http\//) {
+ push @testsToRun, $test;
+ }
+ } elsif (-d $fullPath) {
+ find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $fullPath);
+ for my $level (@platformTestHierarchy) {
+ my $platformPath = catfile($level, $test);
+ find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $platformPath) if (-d $platformPath);
+ }
+ } else {
+ print "test $test not found\n";
+ }
+ }
+
+ if (!scalar @ARGV) {
+ find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $testDirectory);
+ for my $level (@platformTestHierarchy) {
+ find({ preprocess => \&directoryFilter, wanted => \&fileFilter }, $level);
+ }
+ }
+
+ @testsToRun = sort pathcmp @testsToRun;
+
+ # Reverse the tests
+ @testsToRun = reverse @testsToRun if $reverseTests;
+
+ # Shuffle the array
+ @testsToRun = shuffle(@testsToRun) if $randomizeTests;
+
+ return @testsToRun;
+}
+
+sub printResults
+{
+ my %text = (
+ match => "succeeded",
+ mismatch => "had incorrect layout",
+ new => "were new",
+ timedout => "timed out",
+ crash => "crashed",
+ error => "had stderr output"
+ );
+
+ for my $type ("match", "mismatch", "new", "timedout", "crash", "error") {
+ my $typeCount = $counts{$type};
+ next unless $typeCount;
+ my $typeText = $text{$type};
+ my $message;
+ if ($typeCount == 1) {
+ $typeText =~ s/were/was/;
+ $message = sprintf "1 test case (%d%%) %s\n", 1 * 100 / $count, $typeText;
+ } else {
+ $message = sprintf "%d test cases (%d%%) %s\n", $typeCount, $typeCount * 100 / $count, $typeText;
+ }
+ $message =~ s-\(0%\)-(<1%)-;
+ print $message;
+ }
+}