summaryrefslogtreecommitdiffstats
path: root/webkit/tools/layout_tests
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-27 00:20:51 +0000
commitf5b16fed647e941aa66933178da85db2860d639b (patch)
treef00e9856c04aad3b558a140955e7674add33f051 /webkit/tools/layout_tests
parent920c091ac3ee15079194c82ae8a7a18215f3f23c (diff)
downloadchromium_src-f5b16fed647e941aa66933178da85db2860d639b.zip
chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.gz
chromium_src-f5b16fed647e941aa66933178da85db2860d639b.tar.bz2
Add webkit to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/tools/layout_tests')
-rw-r--r--webkit/tools/layout_tests/layout_package/__init__.py0
-rw-r--r--webkit/tools/layout_tests/layout_package/compare_failures.py170
-rw-r--r--webkit/tools/layout_tests/layout_package/compare_failures_unittest.py305
-rw-r--r--webkit/tools/layout_tests/layout_package/http_server.py219
-rw-r--r--webkit/tools/layout_tests/layout_package/lighttpd.conf74
-rw-r--r--webkit/tools/layout_tests/layout_package/path_utils.py190
-rw-r--r--webkit/tools/layout_tests/layout_package/platform_utils.py46
-rw-r--r--webkit/tools/layout_tests/layout_package/platform_utils_win.py168
-rw-r--r--webkit/tools/layout_tests/layout_package/test_expectations.py368
-rw-r--r--webkit/tools/layout_tests/layout_package/test_failures.py215
-rw-r--r--webkit/tools/layout_tests/layout_package/test_shell_thread.py301
-rw-r--r--webkit/tools/layout_tests/layout_package/test_types_unittest.py71
-rw-r--r--webkit/tools/layout_tests/run_webkit_tests.py653
-rwxr-xr-xwebkit/tools/layout_tests/run_webkit_tests.sh9
-rw-r--r--webkit/tools/layout_tests/test_lists/README34
-rw-r--r--webkit/tools/layout_tests/test_lists/tests_fixable.txt718
-rw-r--r--webkit/tools/layout_tests/test_lists/tests_ignored.txt177
-rw-r--r--webkit/tools/layout_tests/test_types/__init__.py0
-rw-r--r--webkit/tools/layout_tests/test_types/image_diff.py133
-rw-r--r--webkit/tools/layout_tests/test_types/simplified_text_diff.py141
-rw-r--r--webkit/tools/layout_tests/test_types/test_type_base.py189
-rw-r--r--webkit/tools/layout_tests/test_types/text_diff.py95
-rw-r--r--webkit/tools/layout_tests/testdata/README2
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/form-element-geometry-actual-win.txt369
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/form-element-geometry-expected.txt365
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/null-offset-parent-actual-win.txt82
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/null-offset-parent-expected.txt82
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-actual-win.txt75
-rw-r--r--webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-expected.txt74
-rw-r--r--webkit/tools/layout_tests/testdata/expected-crashes-new-passing.txt2
-rw-r--r--webkit/tools/layout_tests/testdata/expected-crashes-new-test.txt4
-rw-r--r--webkit/tools/layout_tests/testdata/expected-crashes.txt3
-rw-r--r--webkit/tools/layout_tests/testdata/expected-failures-added.txt4
-rw-r--r--webkit/tools/layout_tests/testdata/expected-failures-new-crash.txt4
-rw-r--r--webkit/tools/layout_tests/testdata/expected-failures-new-passing.txt2
-rw-r--r--webkit/tools/layout_tests/testdata/expected-failures-new-test.txt4
-rw-r--r--webkit/tools/layout_tests/testdata/expected-failures.txt3
-rw-r--r--webkit/tools/layout_tests/testdata/expected-passing-new-baseline.txt1
-rw-r--r--webkit/tools/layout_tests/testdata/expected-passing-new-passing.txt3
-rw-r--r--webkit/tools/layout_tests/testdata/expected-passing-new-passing2.txt3
-rw-r--r--webkit/tools/layout_tests/testdata/expected-passing-new-test.txt3
-rw-r--r--webkit/tools/layout_tests/testdata/expected-passing.txt2
42 files changed, 5363 insertions, 0 deletions
diff --git a/webkit/tools/layout_tests/layout_package/__init__.py b/webkit/tools/layout_tests/layout_package/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/__init__.py
diff --git a/webkit/tools/layout_tests/layout_package/compare_failures.py b/webkit/tools/layout_tests/layout_package/compare_failures.py
new file mode 100644
index 0000000..5931ef4
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/compare_failures.py
@@ -0,0 +1,170 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A helper class for comparing the failures and crashes between layout test
+runs. The results from the last test run are stored in expected-failures.txt
+and expected-crashes.txt in the layout test results directory."""
+
+import errno
+import os
+
+import path_utils
+import test_failures
+import test_expectations
+
+
+def PrintFilesFromSet(filenames, header_text):
+ """A helper method to print a list of files to stdout.
+
+ Args:
+ filenames: a list of absolute filenames
+ header_text: a string to display before the list of filenames
+ """
+ if not len(filenames):
+ return
+
+ filenames = list(filenames)
+ filenames.sort()
+ print
+ print header_text, "(%d):" % len(filenames)
+ for filename in filenames:
+ print " %s" % path_utils.RelativeTestFilename(filename)
+
+
+class CompareFailures:
+ # A list of which TestFailure classes count as a failure vs a crash.
+ FAILURE_TYPES = (test_failures.FailureTextMismatch,
+ test_failures.FailureImageHashMismatch)
+ CRASH_TYPES = (test_failures.FailureCrash,)
+ HANG_TYPES = (test_failures.FailureTimeout,)
+ MISSING_TYPES = (test_failures.FailureMissingResult,
+ test_failures.FailureMissingImageHash)
+
+
+ def __init__(self, test_files, test_failures, expectations):
+ """Read the past layout test run's failures from disk.
+
+ Args:
+ test_files is a set of the filenames of all the test cases we ran
+ test_failures is a dictionary mapping the test filename to a list of
+ TestFailure objects if the test failed
+ expectations is a TestExpectations object representing the
+ current test status
+ """
+ self._test_files = test_files
+ self._test_failures = test_failures
+ self._expectations = expectations
+ self._CalculateRegressions()
+
+
+ def PrintRegressions(self):
+ """Print the regressions computed by _CalculateRegressions() to stdout. """
+
+ print "-" * 78
+
+ # Print unexpected passes by category.
+ passes = self._regressed_passes
+ PrintFilesFromSet(passes & self._expectations.GetFixableFailures(),
+ "Expected to fail, but passed")
+ PrintFilesFromSet(passes & self._expectations.GetFixableTimeouts(),
+ "Expected to timeout, but passed")
+ PrintFilesFromSet(passes & self._expectations.GetFixableCrashes(),
+ "Expected to crash, but passed")
+
+ PrintFilesFromSet(passes & self._expectations.GetIgnoredFailures(),
+ "Expected to fail (ignored), but passed")
+ PrintFilesFromSet(passes & self._expectations.GetIgnoredTimeouts(),
+ "Expected to timeout (ignored), but passed")
+
+ PrintFilesFromSet(passes & self._expectations.GetFixableDeferredFailures(),
+ "Expected to fail (deferred), but passed")
+ PrintFilesFromSet(passes & self._expectations.GetFixableDeferredTimeouts(),
+ "Expected to timeout (deferred), but passed")
+
+ # Print real regressions.
+ PrintFilesFromSet(self._regressed_failures,
+ "Regressions: Unexpected failures")
+ PrintFilesFromSet(self._regressed_hangs,
+ "Regressions: Unexpected timeouts")
+ PrintFilesFromSet(self._regressed_crashes,
+ "Regressions: Unexpected crashes")
+ PrintFilesFromSet(self._missing, "Missing expected results")
+
+
+ def _CalculateRegressions(self):
+ """Calculate regressions from this run through the layout tests."""
+ worklist = self._test_files.copy()
+
+ passes = set()
+ crashes = set()
+ hangs = set()
+ missing = set()
+ failures = set()
+
+ for test, failure_types in self._test_failures.iteritems():
+ # Although each test can have multiple test_failures, we only put them
+ # into one list (either the crash list or the failure list). We give
+ # priority to a crash/timeout over others, and to missing results over
+ # a text mismatch.
+ is_crash = [True for f in failure_types if type(f) in self.CRASH_TYPES]
+ is_hang = [True for f in failure_types if type(f) in self.HANG_TYPES]
+ is_missing = [True for f in failure_types
+ if type(f) in self.MISSING_TYPES]
+ is_failure = [True for f in failure_types
+ if type(f) in self.FAILURE_TYPES]
+ expectations = self._expectations.GetExpectations(test)
+ if is_crash:
+ if not test_expectations.CRASH in expectations: crashes.add(test)
+ elif is_hang:
+ if not test_expectations.TIMEOUT in expectations: hangs.add(test)
+ elif is_missing:
+ missing.add(test)
+ elif is_failure:
+ if not test_expectations.FAIL in expectations: failures.add(test)
+ worklist.remove(test)
+
+ for test in worklist:
+ # Check that all passing tests are expected to pass.
+ expectations = self._expectations.GetExpectations(test)
+ if not test_expectations.PASS in expectations: passes.add(test)
+
+ self._regressed_passes = passes
+ self._regressed_crashes = crashes
+ self._regressed_hangs = hangs
+ self._missing = missing
+ self._regressed_failures = failures
+
+
+ def GetRegressions(self):
+ """Returns a set of regressions from the test expectations. This is
+ used to determine which tests to list in results.html and the
+ right script exit code for the build bots. The list does not
+ include the unexpected passes."""
+ return (self._regressed_failures | self._regressed_hangs |
+ self._regressed_crashes | self._missing)
diff --git a/webkit/tools/layout_tests/layout_package/compare_failures_unittest.py b/webkit/tools/layout_tests/layout_package/compare_failures_unittest.py
new file mode 100644
index 0000000..a33b5fc
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/compare_failures_unittest.py
@@ -0,0 +1,305 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unittests to make sure we generate and update the expected-*.txt files
+properly after running layout tests."""
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import compare_failures
+import path_utils
+import test_failures
+
+class CompareFailuresUnittest(unittest.TestCase):
+ def setUp(self):
+ """Makes a temporary results directory and puts expected-failures.txt and
+ expected-crashes.txt into it."""
+ self._tempdir = tempfile.mkdtemp()
+ # copy over expected-*.txt files
+ testdatadir = self.GetTestDataDir()
+ filenames = ("expected-passing.txt", "expected-failures.txt",
+ "expected-crashes.txt")
+ for filename in filenames:
+ # copyfile doesn't copy file permissions so we can delete the files later
+ shutil.copyfile(os.path.join(testdatadir, filename),
+ os.path.join(self._tempdir, filename))
+
+ def tearDown(self):
+ """Remove temp directory."""
+ shutil.rmtree(self._tempdir)
+ self._tempdir = None
+
+ ###########################################################################
+ # Tests
+ def testGenerateNewBaseline(self):
+ """Test the generation of new expected-*.txt files when either they don't
+ exist or the user explicitly asks to make new files."""
+ failures = self.GetTestFailures()
+
+ # Test to make sure we generate baseline files if the file doesn't exist.
+ os.remove(os.path.join(self.GetTmpDir(), 'expected-passing.txt'))
+ os.remove(os.path.join(self.GetTmpDir(), 'expected-failures.txt'))
+ os.remove(os.path.join(self.GetTmpDir(), 'expected-crashes.txt'))
+
+ # Test force generation of new baseline files with a new failure and one
+ # less passing.
+ pass_file = os.path.join(path_utils.LayoutDataDir(), 'fast', 'pass1.html')
+ failures[pass_file] = [test_failures.FailureTextMismatch(None)]
+
+ cf = compare_failures.CompareFailures(self.GetTestFiles(), failures,
+ set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing-new-baseline.txt',
+ 'expected-failures-added.txt',
+ 'expected-crashes.txt')
+
+ def testPassingToFailure(self):
+ """When there's a new failure, we don't add it to the baseline."""
+ failures = self.GetTestFailures()
+
+ # Test case where we don't update new baseline. We have a new failure,
+ # but it shouldn't be added to the expected-failures.txt file.
+ pass_file = os.path.join(path_utils.LayoutDataDir(), 'fast', 'pass1.html')
+ failures[pass_file] = [test_failures.FailureTextMismatch(None)]
+ self.CheckNoChanges(failures)
+
+ # Same thing as before: pass -> crash
+ failures[pass_file] = [test_failures.FailureCrash()]
+ self.CheckNoChanges(failures)
+
+ def testFailureToCrash(self):
+ """When there's a new crash, we don't add it to the baseline or remove it
+ from the failure list."""
+ failures = self.GetTestFailures()
+
+ # Test case where we don't update new baseline. A failure moving to a
+ # crash shouldn't be added to the expected-crashes.txt file.
+ failure_file = os.path.join(path_utils.LayoutDataDir(),
+ 'fast', 'foo', 'fail1.html')
+ failures[failure_file] = [test_failures.FailureCrash()]
+ self.CheckNoChanges(failures)
+
+ def testFailureToPassing(self):
+ """This is better than before, so we should update the failure list."""
+ failures = self.GetTestFailures()
+
+ # Remove one of the failing test cases from the failures dictionary. This
+ # makes failure_file considered to be passing.
+ failure_file = os.path.join(path_utils.LayoutDataDir(),
+ 'fast', 'bar', 'fail2.html')
+ del failures[failure_file]
+
+ cf = compare_failures.CompareFailures(self.GetTestFiles(), failures,
+ set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing-new-passing2.txt',
+ 'expected-failures-new-passing.txt',
+ 'expected-crashes.txt')
+
+ def testCrashToPassing(self):
+ """This is better than before, so we update the crashes file."""
+ failures = self.GetTestFailures()
+
+ crash_file = os.path.join(path_utils.LayoutDataDir(),
+ 'fast', 'bar', 'betz', 'crash3.html')
+ del failures[crash_file]
+ cf = compare_failures.CompareFailures(self.GetTestFiles(), failures,
+ set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing-new-passing.txt',
+ 'expected-failures.txt',
+ 'expected-crashes-new-passing.txt')
+
+ def testCrashToFailure(self):
+ """This is better than before, so we should update both lists."""
+ failures = self.GetTestFailures()
+
+ crash_file = os.path.join(path_utils.LayoutDataDir(),
+ 'fast', 'bar', 'betz', 'crash3.html')
+ failures[crash_file] = [test_failures.FailureTextMismatch(None)]
+ cf = compare_failures.CompareFailures(self.GetTestFiles(), failures,
+ set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing.txt',
+ 'expected-failures-new-crash.txt',
+ 'expected-crashes-new-passing.txt')
+
+ def testNewTestPass(self):
+ """After a merge, we need to update new passing tests properly."""
+ files = self.GetTestFiles()
+ new_test_file = os.path.join(path_utils.LayoutDataDir(), "new-test.html")
+ files.add(new_test_file)
+ failures = self.GetTestFailures()
+
+ # New test file passing
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing-new-test.txt',
+ 'expected-failures.txt',
+ 'expected-crashes.txt')
+
+ def testNewTestFail(self):
+ """After a merge, we need to update new failing tests properly."""
+ files = self.GetTestFiles()
+ new_test_file = os.path.join(path_utils.LayoutDataDir(), "new-test.html")
+ files.add(new_test_file)
+ failures = self.GetTestFailures()
+
+ # New test file failing
+ failures[new_test_file] = [test_failures.FailureTextMismatch(None)]
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing.txt',
+ 'expected-failures-new-test.txt',
+ 'expected-crashes.txt')
+
+ def testNewTestCrash(self):
+ """After a merge, we need to update new crashing tests properly."""
+ files = self.GetTestFiles()
+ new_test_file = os.path.join(path_utils.LayoutDataDir(), "new-test.html")
+ files.add(new_test_file)
+ failures = self.GetTestFailures()
+
+ # New test file crashing
+ failures[new_test_file] = [test_failures.FailureCrash()]
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing.txt',
+ 'expected-failures.txt',
+ 'expected-crashes-new-test.txt')
+
+ def testHasNewFailures(self):
+ files = self.GetTestFiles()
+ failures = self.GetTestFailures()
+
+ # no changes, no new failures
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ self.failUnless(not cf.HasNewFailures())
+
+ # test goes from passing to failing
+ pass_file = os.path.join(path_utils.LayoutDataDir(), 'fast', 'pass1.html')
+ failures[pass_file] = [test_failures.FailureTextMismatch(None)]
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ self.failUnless(cf.HasNewFailures())
+
+ # Failing to passing
+ failures = self.GetTestFailures()
+ failure_file = os.path.join(path_utils.LayoutDataDir(),
+ 'fast', 'bar', 'fail2.html')
+ del failures[failure_file]
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ self.failUnless(not cf.HasNewFailures())
+
+ # A new test that fails, this doesn't count as a new failure.
+ new_test_file = os.path.join(path_utils.LayoutDataDir(), "new-test.html")
+ files.add(new_test_file)
+ failures = self.GetTestFailures()
+ failures[new_test_file] = [test_failures.FailureCrash()]
+ cf = compare_failures.CompareFailures(files, failures, set(), set(),
+ self.GetTmpDir(), False)
+ self.failUnless(not cf.HasNewFailures())
+
+
+ ###########################################################################
+ # Helper methods
+ def CheckOutputEqualsExpectedFile(self, output, expected):
+ """Compares a file in our output dir against a file from the testdata
+ directory."""
+ output = os.path.join(self.GetTmpDir(), output)
+ expected = os.path.join(self.GetTestDataDir(), expected)
+ self.failUnlessEqual(open(output).read(), open(expected).read())
+
+ def CheckOutputWithExpectedFiles(self, passing, failing, crashing):
+ """Compare all three output files against three provided expected
+ files."""
+ self.CheckOutputEqualsExpectedFile('expected-passing.txt', passing)
+ self.CheckOutputEqualsExpectedFile('expected-failures.txt', failing)
+ self.CheckOutputEqualsExpectedFile('expected-crashes.txt', crashing)
+
+ def CheckNoChanges(self, failures):
+ """Verify that none of the expected-*.txt files have changed."""
+ cf = compare_failures.CompareFailures(self.GetTestFiles(), failures,
+ set(), set(),
+ self.GetTmpDir(), False)
+ cf.UpdateFailuresOnDisk()
+ self.CheckOutputWithExpectedFiles('expected-passing.txt',
+ 'expected-failures.txt',
+ 'expected-crashes.txt')
+
+ def GetTestDataDir(self):
+ return os.path.abspath('testdata')
+
+ def GetTmpDir(self):
+ return self._tempdir
+
+ def GetTestFiles(self):
+ """Get a set of files that includes the expected crashes and failures
+ along with two passing tests."""
+ layout_dir = path_utils.LayoutDataDir()
+ files = [
+ 'fast\\pass1.html',
+ 'fast\\foo\\pass2.html',
+ 'fast\\foo\\crash1.html',
+ 'fast\\bar\\crash2.html',
+ 'fast\\bar\\betz\\crash3.html',
+ 'fast\\foo\\fail1.html',
+ 'fast\\bar\\fail2.html',
+ 'fast\\bar\\betz\\fail3.html',
+ ]
+
+ return set([os.path.join(layout_dir, f) for f in files])
+
+ def GetTestFailures(self):
+ """Get a dictionary representing the crashes and failures in the
+ expected-*.txt files."""
+ failures = {}
+ for filename in self.GetTestFiles():
+ if filename.find('crash') != -1:
+ failures[filename] = [test_failures.FailureCrash()]
+ elif filename.find('fail') != -1:
+ failures[filename] = [test_failures.FailureTextMismatch(None)]
+
+ return failures
+
+if '__main__' == __name__:
+ unittest.main()
diff --git a/webkit/tools/layout_tests/layout_package/http_server.py b/webkit/tools/layout_tests/layout_package/http_server.py
new file mode 100644
index 0000000..aac1cca
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/http_server.py
@@ -0,0 +1,219 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A class to help start/stop the lighttpd server used by layout tests."""
+
+
+import logging
+import optparse
+import os
+import subprocess
+import sys
+import time
+import urllib
+
+import google.path_utils
+
+# This will be a native path to the directory this file resides in.
+# It can either be relative or absolute depending how it's executed.
+THISDIR = os.path.dirname(os.path.abspath(__file__))
+
+def PathFromBase(*pathies):
+ return google.path_utils.FindUpward(THISDIR, *pathies)
+
+class HttpdNotStarted(Exception):
+ pass
+
+class Lighttpd:
+ # Webkit tests
+ _webkit_tests = PathFromBase('webkit', 'data', 'layout_tests',
+ 'LayoutTests', 'http', 'tests')
+ # New tests for Chrome
+ _pending_tests = PathFromBase('webkit', 'data', 'layout_tests',
+ 'pending', 'http', 'tests')
+ # Path where we can access all of the tests
+ _all_tests = PathFromBase('webkit', 'data', 'layout_tests')
+ # Self generated certificate for SSL server (for client cert get
+ # <base-path>\chrome\test\data\ssl\certs\root_ca_cert.crt)
+ _pem_file = PathFromBase('tools', 'python', 'google', 'httpd_config',
+ 'httpd2.pem')
+ VIRTUALCONFIG = [
+ # Three mappings (one with SSL enabled) for LayoutTests http tests
+ {'port': 8000, 'docroot': _webkit_tests},
+ {'port': 8080, 'docroot': _webkit_tests},
+ {'port': 8443, 'docroot': _webkit_tests, 'sslcert': _pem_file},
+ # Three similar mappings (one with SSL enabled) for pending http tests
+ {'port': 9000, 'docroot': _pending_tests},
+ {'port': 9080, 'docroot': _pending_tests},
+ {'port': 9443, 'docroot': _pending_tests, 'sslcert': _pem_file},
+ # One mapping where we can get to everything
+ {'port': 8081, 'docroot': _all_tests}
+ ]
+
+ def __init__(self, output_dir, background=False):
+ """Args:
+ output_dir: the absolute path to the layout test result directory
+ """
+ self._output_dir = output_dir
+ self._process = None
+
+ def IsRunning(self):
+ return self._process != None
+
+ def Start(self):
+ if self.IsRunning():
+ raise 'Lighttpd already running'
+
+ base_conf_file = os.path.join(THISDIR, 'lighttpd.conf')
+ out_conf_file = os.path.join(self._output_dir, 'lighttpd.conf')
+ access_log = os.path.join(self._output_dir, 'access.log.txt')
+ error_log = os.path.join(self._output_dir, 'error.log.txt')
+
+ # Write out the config
+ f = file(base_conf_file, 'rb')
+ base_conf = f.read()
+ f.close()
+
+ f = file(out_conf_file, 'wb')
+ f.write(base_conf)
+
+ # Write out our cgi handlers. Run perl through env so that it processes
+ # the #! line and runs perl with the proper command line arguments.
+ # Emulate apache's mod_asis with a cat cgi handler.
+ f.write(('cgi.assign = ( ".cgi" => "/usr/bin/env",\n'
+ ' ".pl" => "/usr/bin/env",\n'
+ ' ".asis" => "/usr/bin/cat",\n'
+ ' ".php" => "%s" )\n\n') %
+ PathFromBase('third_party', 'lighttpd', 'php5', 'php-cgi.exe'))
+
+ # Setup log files
+ f.write(('server.errorlog = "%s"\n'
+ 'accesslog.filename = "%s"\n\n') % (error_log, access_log))
+
+ # dump out of virtual host config at the bottom.
+ for mapping in self.VIRTUALCONFIG:
+ ssl_setup = ''
+ if 'sslcert' in mapping:
+ ssl_setup = (' ssl.engine = "enable"\n'
+ ' ssl.pemfile = "%s"\n' % mapping['sslcert'])
+
+ f.write(('$SERVER["socket"] == "127.0.0.1:%d" {\n'
+ ' server.document-root = "%s"\n' +
+ ssl_setup +
+ '}\n\n') % (mapping['port'], mapping['docroot']))
+ f.close()
+
+ start_cmd = [ PathFromBase('third_party', 'lighttpd', 'LightTPD.exe'),
+ # Newly written config file
+ '-f', PathFromBase(self._output_dir, 'lighttpd.conf'),
+ # Where it can find it's module dynamic libraries
+ '-m', PathFromBase('third_party', 'lighttpd', 'lib'),
+ # Don't background
+ '-D' ]
+
+ # Put the cygwin directory first in the path to find cygwin1.dll
+ env = os.environ
+ env['PATH'] = '%s;%s' % (
+ PathFromBase('third_party', 'cygwin', 'bin'), env['PATH'])
+
+ logging.info('Starting http server')
+ self._process = subprocess.Popen(start_cmd, env=env)
+
+ # Ensure that the server is running on all the desired ports.
+ for mapping in self.VIRTUALCONFIG:
+ url = 'http%s://127.0.0.1:%d/' % ('sslcert' in mapping and 's' or '',
+ mapping['port'])
+ if not self._UrlIsAlive(url):
+ raise HttpdNotStarted('Failed to start httpd on port %s' % str(port))
+
+ # Our process terminated already
+ if self._process.returncode != None:
+ raise HttpdNotStarted('Failed to start httpd.')
+
+ def _UrlIsAlive(self, url):
+ """Checks to see if we get an http response from |url|.
+ We poll the url 5 times with a 1 second delay. If we don't
+ get a reply in that time, we give up and assume the httpd
+ didn't start properly.
+
+ Args:
+ url: The URL to check.
+ Return:
+ True if the url is alive.
+ """
+ wait_time = 5
+ while wait_time > 0:
+ try:
+ response = urllib.urlopen(url)
+ # Server is up and responding.
+ return True
+ except IOError:
+ pass
+ wait_time -= 1
+ # Wait a second and try again.
+ time.sleep(1)
+
+ return False
+
+ # TODO(deanm): Find a nicer way to shutdown cleanly. Our log files are
+ # probably not being flushed, etc... why doesn't our python have os.kill ?
+ def Stop(self, force=False):
+ if not force and not self.IsRunning():
+ return
+
+ logging.info('Shutting down http server')
+
+ subprocess.Popen(('taskkill.exe', '/f', '/im', 'LightTPD.exe'),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).wait()
+
+ if self._process:
+ self._process.wait()
+ self._process = None
+
+ # Wait a bit to make sure the ports are free'd up
+ time.sleep(2)
+
+
+if '__main__' == __name__:
+ # Provide some command line params for starting/stopping the http server
+ # manually.
+ option_parser = optparse.OptionParser()
+ option_parser.add_option('-k', '--server', help='Server action (start|stop)')
+ options, args = option_parser.parse_args()
+
+ if not options.server:
+ print "Usage: %s --server {start|stop} [--apache2]" % sys.argv[0]
+ else:
+ httpd = Lighttpd('c:/cygwin/tmp')
+ if 'start' == options.server:
+ httpd.Start()
+ else:
+ httpd.Stop(force=True)
diff --git a/webkit/tools/layout_tests/layout_package/lighttpd.conf b/webkit/tools/layout_tests/layout_package/lighttpd.conf
new file mode 100644
index 0000000..2b53d78
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/lighttpd.conf
@@ -0,0 +1,74 @@
+server.tag = "LightTPD/1.4.19 (Win32)"
+server.modules = ( "mod_accesslog",
+ "mod_cgi",
+ "mod_rewrite" )
+
+# default document root required
+server.document-root = "."
+
+# files to check for if .../ is requested
+index-file.names = ( "index.php", "index.pl", "index.cgi",
+ "index.html", "index.htm", "default.htm" )
+# mimetype mapping
+mimetype.assign = (
+ ".gif" => "image/gif",
+ ".jpg" => "image/jpeg",
+ ".jpeg" => "image/jpeg",
+ ".png" => "image/png",
+ ".css" => "text/css",
+ ".html" => "text/html",
+ ".htm" => "text/html",
+ ".xhtml" => "application/xhtml+xml",
+ ".js" => "text/javascript",
+ ".log" => "text/plain",
+ ".conf" => "text/plain",
+ ".text" => "text/plain",
+ ".txt" => "text/plain",
+ ".dtd" => "text/xml",
+ ".xml" => "text/xml",
+ )
+
+# Use the "Content-Type" extended attribute to obtain mime type if possible
+mimetype.use-xattr = "enable"
+
+##
+# which extensions should not be handle via static-file transfer
+#
+# .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi
+static-file.exclude-extensions = ( ".php", ".pl", ".cgi" )
+
+server.bind = "localhost"
+server.port = 8001
+
+## virtual directory listings
+dir-listing.activate = "enable"
+#dir-listing.encoding = "iso-8859-2"
+#dir-listing.external-css = "style/oldstyle.css"
+
+## enable debugging
+#debug.log-request-header = "enable"
+#debug.log-response-header = "enable"
+#debug.log-request-handling = "enable"
+#debug.log-file-not-found = "enable"
+
+#### SSL engine
+#ssl.engine = "enable"
+#ssl.pemfile = "server.pem"
+
+# Rewrite rule for utf-8 path test (LayoutTests/http/tests/uri/utf8-path.html)
+# See the apache rewrite rule at LayoutTests/http/tests/uri/intercept/.htaccess
+url.rewrite-once = ( "^/uri/intercept/(.*)" => "/uri/resources/print-uri.php" )
+
+# LayoutTests/http/tests/xmlhttprequest/response-encoding.html uses an htaccess
+# to override charset for reply2.txt, reply2.xml, and reply4.txt.
+$HTTP["url"] =~ "^/xmlhttprequest/resources/reply2.(txt|xml)" {
+ mimetype.assign = (
+ ".txt" => "text/plain; charset=windows-1251",
+ ".xml" => "text/xml; charset=windows-1251"
+ )
+}
+$HTTP["url"] =~ "^/xmlhttprequest/resources/reply4.txt" {
+ mimetype.assign = ( ".txt" => "text/plain; charset=koi8-r" )
+}
+
+# Autogenerated test-specific config follows.
diff --git a/webkit/tools/layout_tests/layout_package/path_utils.py b/webkit/tools/layout_tests/layout_package/path_utils.py
new file mode 100644
index 0000000..292d298
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/path_utils.py
@@ -0,0 +1,190 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Some utility methods for getting paths used by run_webkit_tests.py.
+"""
+
+import errno
+import os
+import subprocess
+import sys
+
+import google.path_utils
+
+
+class PathNotFound(Exception): pass
+
+# Save some paths here so we don't keep re-evaling.
+_webkit_root = None
+_layout_data_dir = None
+_expected_results_dir = None
+_platform_results_dirs = {}
+
+# TODO this should probably be moved into path_utils as ToUnixPath().
+def WinPathToUnix(path):
+ """Convert a windows path to use unix-style path separators (a/b/c)."""
+ return path.replace('\\', '/')
+
+def WebKitRoot():
+ """Returns the full path to the directory containing webkit.sln. Raises
+ PathNotFound if we're unable to find webkit.sln."""
+ global _webkit_root
+ if _webkit_root:
+ return _webkit_root
+ webkit_sln_path = google.path_utils.FindUpward(google.path_utils.ScriptDir(),
+ 'webkit.sln')
+ _webkit_root = os.path.dirname(webkit_sln_path)
+ return _webkit_root
+
+def LayoutDataDir():
+ """Gets the full path to the tests directory. Raises PathNotFound if
+ we're unable to find it."""
+ global _layout_data_dir
+ if _layout_data_dir:
+ return _layout_data_dir
+ _layout_data_dir = google.path_utils.FindUpward(WebKitRoot(), 'webkit',
+ 'data', 'layout_tests')
+ return _layout_data_dir
+
+def ExpectedResultsDir():
+ """Gets the full path to the custom_results directory. Raises
+ PathNotFound if we're unable to find it."""
+ global _expected_results_dir
+ if _expected_results_dir:
+ return _expected_results_dir
+ _expected_results_dir = google.path_utils.FindUpward(WebKitRoot(), 'webkit',
+ 'data',
+ 'layout_test_results')
+ return _expected_results_dir
+
+def CustomExpectedResultsDir(custom_id):
+ """Gets the full path to the directory in which custom expected results for
+ this app and build type are located.
+
+ Args:
+ custom_id: a string specifying the particular set of results to use (e.g.,
+ 'v8' or 'kjs')
+ """
+ return os.path.join(ExpectedResultsDir(), custom_id)
+
+def PlatformResultsDir(name):
+ """Gets the full path to a platform-specific results directory. Raises
+ PathNotFound if we're unable to find it."""
+ global _platform_results_dirs
+ if _platform_results_dirs.get(name):
+ return _platform_results_dirs[name]
+ _platform_results_dirs[name] = google.path_utils.FindUpward(WebKitRoot(),
+ 'webkit', 'data', 'layout_tests', 'LayoutTests', 'platform', name)
+ return _platform_results_dirs[name]
+
+def ExpectedFilename(filename, suffix, custom_result_id):
+ """Given a test name, returns an absolute filename to the most specific
+ applicable file of expected results.
+
+ Args:
+ filename: absolute filename to test file
+ suffix: file suffix of the expected results, including dot; e.g. '.txt'
+ or '.png'. This should not be None, but may be an empty string.
+ custom_result_id: Tells us where to look for custom results. Currently
+ this is either kjs or v8.
+
+ Return:
+ If a file named <testname>-expected<suffix> exists in the subdirectory
+ of the ExpectedResultsDir() specified by this platform's identifier,
+ return its absolute path. Otherwise, return a path to a
+ <testname>-expected<suffix> file under the MacExpectedResultsDir() or
+ <testname>-expected<suffix> file under the MacLeopardExpectedResultsDir()
+ or (if not found there) in the same directory as the test file (even if
+ that default file does not exist).
+ """
+ testname = os.path.splitext(RelativeTestFilename(filename))[0]
+ results_filename = testname + '-expected' + suffix
+ results_dirs = [
+ CustomExpectedResultsDir(custom_result_id),
+ CustomExpectedResultsDir('common'),
+ LayoutDataDir()
+ ]
+
+ for results_dir in results_dirs:
+ platform_file = os.path.join(results_dir, results_filename)
+ if os.path.exists(platform_file):
+ return platform_file
+
+ # for 'base' tests, we need to look for mac-specific results
+ if testname.startswith('LayoutTests'):
+ layout_test_results_dirs = [
+ PlatformResultsDir('mac'),
+ PlatformResultsDir('mac-leopard'),
+ PlatformResultsDir('mac-tiger')
+ ]
+ rel_testname = testname[len('LayoutTests') + 1:]
+ rel_filename = rel_testname + '-expected' + suffix
+ for results_dir in layout_test_results_dirs:
+ platform_file = os.path.join(results_dir, rel_filename)
+ if os.path.exists(platform_file):
+ return platform_file
+
+ # Failed to find the results anywhere, return default path anyway
+ return os.path.join(results_dirs[0], results_filename)
+
+def TestShellBinary():
+ """Returns the name of the test_shell executable."""
+ return 'test_shell.exe'
+
+def TestShellBinaryPath(target):
+ """Gets the full path to the test_shell binary for the target build
+ configuration. Raises PathNotFound if the file doesn't exist"""
+ full_path = os.path.join(WebKitRoot(), target, TestShellBinary())
+ if not os.path.exists(full_path):
+ # try chrome's output directory in case test_shell was built by chrome.sln
+ full_path = google.path_utils.FindUpward(WebKitRoot(), 'chrome', target,
+ TestShellBinary())
+ if not os.path.exists(full_path):
+ raise PathNotFound('unable to find test_shell at %s' % full_path)
+ return full_path
+
+def RelativeTestFilename(filename):
+ """Provide the filename of the test relative to the layout data
+ directory as a unix style path (a/b/c)."""
+ return WinPathToUnix(filename[len(LayoutDataDir()) + 1:])
+
+# Map platform specific path utility functions. We do this as a convenience
+# so importing path_utils will get all path related functions even if they are
+# platform specific.
+def GetAbsolutePath(path):
+ # Avoid circular import by delaying it.
+ import layout_package.platform_utils
+ platform_util = layout_package.platform_utils.PlatformUtility(WebKitRoot())
+ return platform_util.GetAbsolutePath(path)
+
+def FilenameToUri(path):
+ # Avoid circular import by delaying it.
+ import layout_package.platform_utils
+ platform_util = layout_package.platform_utils.PlatformUtility(WebKitRoot())
+ return platform_util.FilenameToUri(path)
diff --git a/webkit/tools/layout_tests/layout_package/platform_utils.py b/webkit/tools/layout_tests/layout_package/platform_utils.py
new file mode 100644
index 0000000..1fcb182
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/platform_utils.py
@@ -0,0 +1,46 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Platform-specific utilities and pseudo-constants
+
+Any functions whose implementations or values differ from one platform to
+another should be defined in their respective platform_utils_<platform>.py
+modules. The appropriate one of those will be imported into this module to
+provide callers with a common, platform-independent interface.
+"""
+
+import sys
+
+# We may not support the version of Python that a user has installed (Cygwin
+# especially has had problems), but we'll allow the platform utils to be
+# included in any case so we don't get an import error.
+if sys.platform in ('cygwin', 'win32'):
+ from platform_utils_win import *
+
diff --git a/webkit/tools/layout_tests/layout_package/platform_utils_win.py b/webkit/tools/layout_tests/layout_package/platform_utils_win.py
new file mode 100644
index 0000000..542533a
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/platform_utils_win.py
@@ -0,0 +1,168 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Platform specific utility methods. This file contains methods that are
+specific to running the layout tests on windows.
+
+This file constitutes a complete wrapper for google.platform_utils_win,
+implementing or mapping all needed functions from there. Layout-test scripts
+should be able to import only this file (via platform_utils.py), with no need
+to fall back to the base functions.
+"""
+
+import os
+import re
+import subprocess
+
+import google.httpd_utils
+import google.path_utils
+import google.platform_utils_win
+
+import layout_package.path_utils
+
+
+class PlatformUtility(google.platform_utils_win.PlatformUtility):
+ """Overrides base PlatformUtility methods as needed for layout tests."""
+
+ LAYOUTTEST_HTTP_DIR = "LayoutTests/http/tests/"
+ PENDING_HTTP_DIR = "pending/http/tests/"
+
+ def FilenameToUri(self, full_path):
+ relative_path = layout_package.path_utils.RelativeTestFilename(full_path)
+ port = None
+ use_ssl = False
+
+ # LayoutTests/http/tests/ run off port 8000 and ssl/ off 8443
+ if relative_path.startswith(self.LAYOUTTEST_HTTP_DIR):
+ relative_path = relative_path[len(self.LAYOUTTEST_HTTP_DIR):]
+ port = 8000
+ # pending/http/tests/ run off port 9000 and ssl/ off 9443
+ elif relative_path.startswith(self.PENDING_HTTP_DIR):
+ relative_path = relative_path[len(self.PENDING_HTTP_DIR):]
+ port = 9000
+ # chrome/http/tests run off of port 8081 with the full path
+ elif relative_path.find("/http/") >= 0:
+ print relative_path
+ port = 8081
+
+ # We want to run off of the http server
+ if port:
+ if relative_path.startswith("ssl/"):
+ port += 443
+ use_ssl = True
+ return google.platform_utils_win.PlatformUtility.FilenameToUri(self,
+ relative_path,
+ use_http=True,
+ use_ssl=use_ssl,
+ port=port)
+
+ # Run off file://
+ return google.platform_utils_win.PlatformUtility.FilenameToUri(
+ self, full_path)
+
+ def KillAllTestShells(self):
+ """Kills all instances of the test_shell binary currently running."""
+ subprocess.Popen(('taskkill.exe', '/f', '/im',
+ layout_package.path_utils.TestShellBinary()),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).wait()
+
+ def _GetVirtualHostConfig(self, document_root, port, ssl=False):
+ """Returns a <VirtualHost> directive block for an httpd.conf file. It will
+ listen to 127.0.0.1 on each of the given port.
+ """
+ cygwin_document_root = google.platform_utils_win.GetCygwinPath(
+ document_root)
+
+ return '\n'.join(('<VirtualHost 127.0.0.1:%s>' % port,
+ 'DocumentRoot %s' % cygwin_document_root,
+ ssl and 'SSLEngine On' or '',
+ '</VirtualHost>', ''))
+
+ def GetStartHttpdCommand(self, output_dir, apache2=False):
+ """Prepares the config file and output directory to start an httpd server.
+ Returns a list of strings containing the server's command line+args.
+
+ Creates the test output directory and generates an httpd.conf (or
+ httpd2.conf for Apache 2 if apache2 is True) file in it that contains
+ the necessary <VirtualHost> directives for running all the http tests.
+
+ WebKit http tests expect the DocumentRoot to be in LayoutTests/http/tests/,
+ but that prevents us from running http tests in chrome/ or pending/. So we
+ run two virtual hosts, one on ports 8000 and 8080 for WebKit, and one on
+ port 8081 with a much broader DocumentRoot for everything else. (Note that
+ WebKit http tests that have been modified and are temporarily in pending/
+ will still fail, if they expect the DocumentRoot to be located as described
+ above.)
+
+ Args:
+ output_dir: the path to the test output directory. It will be created.
+ apache2: boolean if true will cause this function to return start
+ command for Apache 2.x instead of Apache 1.3.x
+ """
+ layout_dir = google.platform_utils_win.GetCygwinPath(
+ layout_package.path_utils.LayoutDataDir())
+ main_document_root = os.path.join(layout_dir, "LayoutTests",
+ "http", "tests")
+ pending_document_root = os.path.join(layout_dir, "pending",
+ "http", "tests")
+ chrome_document_root = layout_dir
+ apache_config_dir = google.httpd_utils.ApacheConfigDir(self._base_dir)
+ mime_types_path = os.path.join(apache_config_dir, "mime.types")
+
+ conf_file_name = "httpd.conf"
+ if apache2:
+ conf_file_name = "httpd2.conf"
+ # Make the test output directory and place the generated httpd.conf in it.
+ orig_httpd_conf_path = os.path.join(apache_config_dir, conf_file_name)
+
+ httpd_conf_path = os.path.join(output_dir, conf_file_name)
+ google.path_utils.MaybeMakeDirectory(output_dir)
+ httpd_conf = open(orig_httpd_conf_path).read()
+ httpd_conf = (httpd_conf +
+ self._GetVirtualHostConfig(main_document_root, 8000) +
+ self._GetVirtualHostConfig(main_document_root, 8080) +
+ self._GetVirtualHostConfig(pending_document_root, 9000) +
+ self._GetVirtualHostConfig(pending_document_root, 9080) +
+ self._GetVirtualHostConfig(chrome_document_root, 8081))
+ if apache2:
+ httpd_conf += self._GetVirtualHostConfig(main_document_root, 8443,
+ ssl=True)
+ httpd_conf += self._GetVirtualHostConfig(pending_document_root, 9443,
+ ssl=True)
+ f = open(httpd_conf_path, 'wb')
+ f.write(httpd_conf)
+ f.close()
+
+ return google.platform_utils_win.PlatformUtility.GetStartHttpdCommand(
+ self,
+ output_dir,
+ httpd_conf_path,
+ mime_types_path,
+ apache2=apache2)
diff --git a/webkit/tools/layout_tests/layout_package/test_expectations.py b/webkit/tools/layout_tests/layout_package/test_expectations.py
new file mode 100644
index 0000000..7ea0fb1
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/test_expectations.py
@@ -0,0 +1,368 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A helper class for reading in and dealing with tests expectations
+for layout tests. """
+
+import os
+import re
+import path_utils
+import compare_failures
+
+
+# Test expectation constants.
+PASS = 0
+FAIL = 1
+TIMEOUT = 2
+CRASH = 3
+
+
+class TestExpectations:
+ FIXABLE = "tests_fixable.txt"
+ IGNORED = "tests_ignored.txt"
+
+ def __init__(self, tests, directory, build_type):
+ """Reads the test expectations files from the given directory."""
+ self._tests = tests
+ self._directory = directory
+ self._build_type = build_type
+ self._ReadFiles()
+ self._ValidateLists()
+
+ def GetFixable(self):
+ return (self._fixable.GetTests() -
+ self._fixable.GetNonSkippedDeferred() -
+ self._fixable.GetSkippedDeferred())
+
+ def GetFixableSkipped(self):
+ return self._fixable.GetSkipped()
+
+ def GetFixableSkippedDeferred(self):
+ return self._fixable.GetSkippedDeferred()
+
+ def GetFixableFailures(self):
+ return (self._fixable.GetTestsExpectedTo(FAIL) -
+ self._fixable.GetTestsExpectedTo(TIMEOUT) -
+ self._fixable.GetTestsExpectedTo(CRASH) -
+ self._fixable.GetNonSkippedDeferred())
+
+ def GetFixableTimeouts(self):
+ return (self._fixable.GetTestsExpectedTo(TIMEOUT) -
+ self._fixable.GetTestsExpectedTo(CRASH) -
+ self._fixable.GetNonSkippedDeferred())
+
+ def GetFixableCrashes(self):
+ return self._fixable.GetTestsExpectedTo(CRASH)
+
+ def GetFixableDeferred(self):
+ return self._fixable.GetNonSkippedDeferred()
+
+ def GetFixableDeferredFailures(self):
+ return (self._fixable.GetNonSkippedDeferred() &
+ self._fixable.GetTestsExpectedTo(FAIL))
+
+ def GetFixableDeferredTimeouts(self):
+ return (self._fixable.GetNonSkippedDeferred() &
+ self._fixable.GetTestsExpectedTo(TIMEOUT))
+
+ def GetIgnored(self):
+ return self._ignored.GetTests()
+
+ def GetIgnoredSkipped(self):
+ return self._ignored.GetSkipped()
+
+ def GetIgnoredFailures(self):
+ return (self._ignored.GetTestsExpectedTo(FAIL) -
+ self._ignored.GetTestsExpectedTo(TIMEOUT))
+
+ def GetIgnoredTimeouts(self):
+ return self._ignored.GetTestsExpectedTo(TIMEOUT)
+
+ def GetExpectations(self, test):
+ if self._fixable.Contains(test): return self._fixable.GetExpectations(test)
+ if self._ignored.Contains(test): return self._ignored.GetExpectations(test)
+ # If the test file is not listed in any of the expectations lists
+ # we expect it to pass (and nothing else).
+ return set([PASS])
+
+ def IsFixable(self, test):
+ return (self._fixable.Contains(test) and
+ test not in self._fixable.GetNonSkippedDeferred())
+
+ def IsDeferred(self, test):
+ return (self._fixable.Contains(test) and
+ test in self._fixable.GetNonSkippedDeferred())
+
+ def IsIgnored(self, test):
+ return self._ignored.Contains(test)
+
+ def _ReadFiles(self):
+ self._fixable = self._GetExpectationsFile(self.FIXABLE)
+ self._ignored = self._GetExpectationsFile(self.IGNORED)
+ skipped = self.GetFixableSkipped() | self.GetIgnoredSkipped()
+ self._fixable.PruneSkipped(skipped)
+ self._ignored.PruneSkipped(skipped)
+
+ def _GetExpectationsFile(self, filename):
+ """Read the expectation files for the given filename and return a single
+ expectations file with the merged results.
+ """
+
+ path = os.path.join(self._directory, filename)
+ return TestExpectationsFile(path, self._tests, self._build_type)
+
+ def _ValidateLists(self):
+ # Make sure there's no overlap between the tests in the two files.
+ overlap = self._fixable.GetTests() & self._ignored.GetTests()
+ message = "Files contained in both " + self.FIXABLE + " and " + self.IGNORED
+ compare_failures.PrintFilesFromSet(overlap, message)
+ assert(len(overlap) == 0)
+ # Make sure there are no ignored tests expected to crash.
+ assert(len(self._ignored.GetTestsExpectedTo(CRASH)) == 0)
+
+
+def StripComments(line):
+ """Strips comments from a line and return None if the line is empty
+ or else the contents of line with leading and trailing spaces removed
+ and all other whitespace collapsed"""
+
+ commentIndex = line.find('//')
+ if commentIndex is -1:
+ commentIndex = len(line)
+
+ line = re.sub(r'\s+', ' ', line[:commentIndex].strip())
+ if line == '': return None
+ else: return line
+
+
+class TestExpectationsFile:
+ """Test expectation files consist of lines with specifications of what
+ to expect from layout test cases. The test cases can be directories
+ in which case the expectations apply to all test cases in that
+ directory and any subdirectory. The format of the file is along the
+ lines of:
+
+ KJS # LayoutTests/fast/js/fixme.js = FAIL
+ V8 # LayoutTests/fast/js/flaky.js = FAIL | PASS
+ V8 | KJS # LayoutTests/fast/js/crash.js = CRASH | TIMEOUT | FAIL | PASS
+ ...
+
+ In case you want to skip tests completely, add a SKIP:
+ V8 | KJS # SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT | PASS
+
+ If you want the test to not count in our statistics for the current release,
+ add a DEFER:
+ V8 | KJS # DEFER : LayoutTests/fast/js/no-good.js = TIMEOUT | PASS
+
+ And you can skip + defer a test:
+ V8 | KJS # DEFER | SKIP : LayoutTests/fast/js/no-good.js = TIMEOUT | PASS
+
+ You can also have different expecations for V8 and KJS
+ V8 # LayoutTests/fast/js/no-good.js = TIMEOUT | PASS
+ KJS # DEFER | SKIP : LayoutTests/fast/js/no-good.js = FAIL
+
+ A test can be included twice, but not via the same path. If a test is included
+ twice, then the more precise path wins.
+ """
+
+ EXPECTATIONS = { 'pass': PASS,
+ 'fail': FAIL,
+ 'timeout': TIMEOUT,
+ 'crash': CRASH }
+
+ BUILD_TYPES = [ 'kjs', 'v8' ]
+
+
+ def __init__(self, path, full_test_list, build_type):
+ """path is the path to the expectation file. An error is thrown if a test
+ is listed more than once for a given build_type.
+ full_test_list is the list of all tests to be run pending processing of the
+ expections for those tests.
+ build_type is used to filter out tests that only have expectations for
+ a different build_type.
+
+ """
+
+ self._full_test_list = full_test_list
+ self._skipped = set()
+ self._skipped_deferred = set()
+ self._non_skipped_deferred = set()
+ self._expectations = {}
+ self._test_list_paths = {}
+ self._tests = {}
+ for expectation in self.EXPECTATIONS.itervalues():
+ self._tests[expectation] = set()
+ self._Read(path, build_type)
+
+ def GetSkipped(self):
+ return self._skipped
+
+ def GetNonSkippedDeferred(self):
+ return self._non_skipped_deferred
+
+ def GetSkippedDeferred(self):
+ return self._skipped_deferred
+
+ def GetExpectations(self, test):
+ return self._expectations[test]
+
+ def GetTests(self):
+ return set(self._expectations.keys())
+
+ def GetTestsExpectedTo(self, expectation):
+ return self._tests[expectation]
+
+ def Contains(self, test):
+ return test in self._expectations
+
+ def PruneSkipped(self, skipped):
+ for test in skipped:
+ if not test in self._expectations: continue
+ for expectation in self._expectations[test]:
+ self._tests[expectation].remove(test)
+ del self._expectations[test]
+
+ def _Read(self, path, build_type):
+ """For each test in an expectations file, generate the expectations for it.
+
+ """
+
+ lineno = 0
+ for line in open(path):
+ lineno += 1
+ line = StripComments(line)
+ if not line: continue
+
+ parts = line.split('#')
+ if len(parts) is not 2:
+ self._ReportSyntaxError(path, lineno, "Test must have build types")
+
+ if build_type not in self._GetOptionsList(parts[0]): continue
+
+ parts = parts[1].split(':')
+
+ if len(parts) is 2:
+ test_and_expectations = parts[1]
+ skip_defer_options = self._GetOptionsList(parts[0])
+ is_skipped = 'skip' in skip_defer_options
+ is_deferred = 'defer' in skip_defer_options
+ else:
+ test_and_expectations = parts[0]
+ is_skipped = False
+ is_deferred = False
+
+ tests_and_expecation_parts = test_and_expectations.split('=')
+ if (len(tests_and_expecation_parts) is not 2):
+ self._ReportSyntaxError(path, lineno, "Test is missing expectations")
+
+ test_list_path = tests_and_expecation_parts[0].strip()
+ tests = self._ExpandTests(test_list_path)
+
+ if is_skipped:
+ self._AddSkippedTests(tests, is_deferred)
+ else:
+ try:
+ self._AddTests(tests,
+ self._ParseExpectations(tests_and_expecation_parts[1]),
+ test_list_path,
+ is_deferred)
+ except SyntaxError, err:
+ self._ReportSyntaxError(path, lineno, str(err))
+
+ def _GetOptionsList(self, listString):
+ return [part.strip().lower() for part in listString.split('|')]
+
+ def _ParseExpectations(self, string):
+ result = set()
+ for part in self._GetOptionsList(string):
+ if not part in self.EXPECTATIONS:
+ raise SyntaxError('Unsupported expectation: ' + part)
+ expectation = self.EXPECTATIONS[part]
+ result.add(expectation)
+ return result
+
+ def _ExpandTests(self, test_list_path):
+ # Convert the test specification to an absolute, normalized
+ # path and make sure directories end with the OS path separator.
+ path = os.path.join(path_utils.LayoutDataDir(), test_list_path)
+ path = os.path.normpath(path)
+ if os.path.isdir(path): path = os.path.join(path, '')
+ # This is kind of slow - O(n*m) - since this is called for all
+ # entries in the test lists. It has not been a performance
+ # issue so far. Maybe we should re-measure the time spent reading
+ # in the test lists?
+ result = []
+ for test in self._full_test_list:
+ if test.startswith(path): result.append(test)
+ return result
+
+ def _AddTests(self, tests, expectations, test_list_path, is_deferred):
+ # Do not add tests that we expect only to pass to the lists.
+ # This makes it easier to account for tests that we expect to
+ # consistently pass, because they'll never be represented in
+ # any of the lists.
+ if len(expectations) == 1 and PASS in expectations: return
+ # Traverse all tests and add them with the given expectations.
+
+ for test in tests:
+ if test in self._test_list_paths:
+ prev_base_path = self._test_list_paths[test]
+ if (prev_base_path == os.path.normpath(test_list_path)):
+ raise SyntaxError('Already seen expectations for path ' + test)
+ if prev_base_path.startswith(test_list_path):
+ # already seen a more precise path
+ continue
+
+ # Remove prexisiting expectations for this test.
+ if test in self._test_list_paths:
+ if test in self._non_skipped_deferred:
+ self._non_skipped_deferred.remove(test)
+
+ for expectation in self.EXPECTATIONS.itervalues():
+ if test in self._tests[expectation]:
+ self._tests[expectation].remove(test)
+
+ # Now add the new expectations.
+ self._expectations[test] = expectations
+ self._test_list_paths[test] = os.path.normpath(test_list_path)
+
+ if is_deferred:
+ self._non_skipped_deferred.add(test)
+
+ for expectation in expectations:
+ self._tests[expectation].add(test)
+
+ def _AddSkippedTests(self, tests, is_deferred):
+ for test in tests:
+ self._skipped.add(test)
+ if is_deferred:
+ self._skipped_deferred.add(test)
+
+ def _ReportSyntaxError(self, path, lineno, message):
+ raise SyntaxError(path + ':' + str(lineno) + ': ' + message)
diff --git a/webkit/tools/layout_tests/layout_package/test_failures.py b/webkit/tools/layout_tests/layout_package/test_failures.py
new file mode 100644
index 0000000..685c591
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/test_failures.py
@@ -0,0 +1,215 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Classes for failures that occur during tests."""
+
+import path_utils
+
+class FailureSort(object):
+ """A repository for failure sort orders and tool to facilitate sorting."""
+
+ # Each failure class should have an entry in this dictionary. Sort order 1
+ # will be sorted first in the list. Failures with the same numeric sort
+ # order will be sorted alphabetically by Message().
+ SORT_ORDERS = {
+ 'FailureTextMismatch': 1,
+ 'FailureSimplifiedTextMismatch': 2,
+ 'FailureImageHashMismatch': 3,
+ 'FailureTimeout': 4,
+ 'FailureCrash': 5,
+ 'FailureMissingImageHash': 6,
+ 'FailureMissingImage': 7,
+ 'FailureMissingResult': 8,
+ }
+
+ @staticmethod
+ def SortOrder(failure_type):
+ """Returns a tuple of the class's numeric sort order and its message."""
+ order = FailureSort.SORT_ORDERS.get(failure_type.__name__, -1)
+ return (order, failure_type.Message())
+
+
+class TestFailure(object):
+ """Abstract base class that defines the failure interface."""
+ @staticmethod
+ def Message():
+ """Returns a string describing the failure in more detail."""
+ raise NotImplemented
+
+ def ResultHtmlOutput(self, filename):
+ """Returns an HTML string to be included on the results.html page."""
+ raise NotImplemented
+
+ def ShouldKillTestShell(self):
+ """Returns True if we should kill the test shell before the next test."""
+ return False
+
+
+class FailureWithType(TestFailure):
+ """Base class that produces standard HTML output based on the test type.
+
+ Subclasses may commonly choose to override the ResultHtmlOutput, but still
+ use the standard OutputLinks.
+ """
+ def __init__(self, test_type):
+ TestFailure.__init__(self)
+ self._test_type = test_type
+
+ # Filename suffixes used by ResultHtmlOutput.
+ OUT_FILENAMES = []
+
+ def OutputLinks(self, filename, out_names):
+ """Returns a string holding all applicable output file links.
+
+ Args:
+ filename: the test filename, used to construct the result file names
+ out_names: list of filename suffixes for the files. If three or more
+ suffixes are in the list, they should be [actual, expected, diff].
+ Two suffixes should be [actual, expected], and a single item is the
+ [actual] filename suffix. If out_names is empty, returns the empty
+ string.
+ """
+ links = ['']
+ uris = [self._test_type.RelativeOutputFilename(filename, fn)
+ for fn in out_names]
+ if len(uris) > 1:
+ links.append("<a href='%s'>expected</a>" % uris[1])
+ if len(uris) > 0:
+ links.append("<a href='%s'>actual</a>" % uris[0])
+ if len(uris) > 2:
+ links.append("<a href='%s'>diff</a>" % uris[2])
+ return ' '.join(links)
+
+ def ResultHtmlOutput(self, filename):
+ return self.Message() + self.OutputLinks(filename, self.OUT_FILENAMES)
+
+
+class FailureTimeout(TestFailure):
+ """Test timed out. We also want to restart the test shell if this
+ happens."""
+ @staticmethod
+ def Message():
+ return "Test timed out"
+
+ def ResultHtmlOutput(self, filename):
+ return "<strong>%s</strong>" % self.Message()
+
+ def ShouldKillTestShell(self):
+ return True
+
+
+class FailureCrash(TestFailure):
+ """Test shell crashed."""
+ @staticmethod
+ def Message():
+ return "Test shell crashed"
+
+ def ResultHtmlOutput(self, filename):
+ # TODO(tc): create a link to the minidump file
+ return "<strong>%s</strong>" % self.Message()
+
+ def ShouldKillTestShell(self):
+ return True
+
+
+class FailureMissingResult(FailureWithType):
+ """Expected result was missing."""
+ OUT_FILENAMES = ["-actual-win.txt"]
+
+ @staticmethod
+ def Message():
+ return "No expected results found"
+
+ def ResultHtmlOutput(self, filename):
+ return ("<strong>%s</strong>" % self.Message() +
+ self.OutputLinks(filename, self.OUT_FILENAMES))
+
+
+class FailureTextMismatch(FailureWithType):
+ """Text diff output failed."""
+ # Filename suffixes used by ResultHtmlOutput.
+ OUT_FILENAMES = ["-actual-win.txt", "-expected.txt", "-diff-win.txt"]
+
+ @staticmethod
+ def Message():
+ return "Text diff mismatch"
+
+
+class FailureSimplifiedTextMismatch(FailureTextMismatch):
+ """Simplified text diff output failed.
+
+ The results.html output format is basically the same as regular diff
+ failures (links to expected, actual and diff text files) so we share code
+ with the FailureTextMismatch class.
+ """
+
+ OUT_FILENAMES = ["-simp-actual-win.txt", "-simp-expected.txt",
+ "-simp-diff-win.txt"]
+
+ @staticmethod
+ def Message():
+ return "Simplified text diff mismatch"
+
+
+class FailureMissingImageHash(FailureWithType):
+ """Actual result hash was missing."""
+ # Chrome doesn't know to display a .checksum file as text, so don't bother
+ # putting in a link to the actual result.
+ OUT_FILENAMES = []
+
+ @staticmethod
+ def Message():
+ return "No expected image hash found"
+
+ def ResultHtmlOutput(self, filename):
+ return "<strong>%s</strong>" % self.Message()
+
+
+class FailureMissingImage(FailureWithType):
+ """Actual result image was missing."""
+ OUT_FILENAMES = ["-actual-win.png"]
+
+ @staticmethod
+ def Message():
+ return "No expected image found"
+
+ def ResultHtmlOutput(self, filename):
+ return ("<strong>%s</strong>" % self.Message() +
+ self.OutputLinks(filename, self.OUT_FILENAMES))
+
+
+class FailureImageHashMismatch(FailureWithType):
+ """Image hashes didn't match."""
+ OUT_FILENAMES = ["-actual-win.png", "-expected.png"]
+
+ @staticmethod
+ def Message():
+ # We call this a simple image mismatch to avoid confusion, since we link
+ # to the PNGs rather than the checksums.
+ return "Image mismatch"
diff --git a/webkit/tools/layout_tests/layout_package/test_shell_thread.py b/webkit/tools/layout_tests/layout_package/test_shell_thread.py
new file mode 100644
index 0000000..e28a30e
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/test_shell_thread.py
@@ -0,0 +1,301 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""A Thread object for running the test shell and processing URLs from a
+shared queue.
+
+Each thread runs a separate instance of the test_shell binary and validates
+the output. When there are no more URLs to process in the shared queue, the
+thread exits.
+"""
+
+import copy
+import logging
+import os
+import Queue
+import subprocess
+import thread
+import threading
+
+import path_utils
+import platform_utils
+import test_failures
+
+# The per-test timeout in milliseconds, if no --time-out-ms option was given to
+# run_webkit_tests. This should correspond to the default timeout in
+# test_shell.exe.
+DEFAULT_TEST_TIMEOUT_MS = 10 * 1000
+
+def ProcessOutput(proc, filename, test_uri, test_types, test_args):
+ """Receives the output from a test_shell process, subjects it to a number
+ of tests, and returns a list of failure types the test produced.
+
+ Args:
+ proc: an active test_shell process
+ filename: path of the test file being run
+ test_types: list of test types to subject the output to
+ test_args: arguments to be passed to each test
+
+ Returns: a list of failure objects for the test being processed
+ """
+ outlines = []
+ failures = []
+ crash_or_timeout = False
+
+ # Some test args, such as the image hash, may be added or changed on a
+ # test-by-test basis.
+ local_test_args = copy.copy(test_args)
+
+ line = proc.stdout.readline()
+ while line.rstrip() != "#EOF":
+ # Make sure we haven't crashed.
+ if line == '' and proc.poll() is not None:
+ failures.append(test_failures.FailureCrash())
+
+ # This is hex code 0xc000001d, which is used for abrupt termination.
+ # This happens if we hit ctrl+c from the prompt and we happen to
+ # be waiting on the test_shell.
+ if -1073741510 == proc.returncode:
+ raise KeyboardInterrupt
+ crash_or_timeout = True
+ break
+
+ # Don't include #URL lines in our output
+ if line.startswith("#URL:"):
+ url = line.rstrip()[5:]
+ if url != test_uri:
+ logging.fatal("Test got out of sync:\n|%s|\n|%s|" %
+ (url, test_uri))
+ raise AssertionError("test out of sync")
+ elif line.startswith("#MD5:"):
+ local_test_args.hash = line.rstrip()[5:]
+ elif line.startswith("#TEST_TIMED_OUT"):
+ # Test timed out, but we still need to read until #EOF.
+ crash_or_timeout = True
+ failures.append(test_failures.FailureTimeout())
+ else:
+ outlines.append(line)
+ line = proc.stdout.readline()
+
+ # Check the output and save the results.
+ for test_type in test_types:
+ new_failures = test_type.CompareOutput(filename, proc,
+ ''.join(outlines),
+ local_test_args)
+ # Don't add any more failures if we already have a crash or timeout, so
+ # we don't double-report those tests.
+ if not crash_or_timeout:
+ failures.extend(new_failures)
+
+ return failures
+
+
+def StartTestShell(binary, args):
+ """Returns the process for a new test_shell started in layout-tests mode."""
+ cmd = [binary, '--layout-tests'] + args
+ return subprocess.Popen(cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+
+class SingleTestThread(threading.Thread):
+ """Thread wrapper for running a single test file."""
+ def __init__(self, test_shell_binary, shell_args, test_uri, filename,
+ test_types, test_args):
+ """
+ Args:
+ test_uri: full file:// or http:// URI of the test file to be run
+ filename: absolute local path to the test file
+ See TestShellThread for documentation of the remaining arguments.
+ """
+
+ threading.Thread.__init__(self)
+ self._binary = test_shell_binary
+ self._shell_args = shell_args
+ self._test_uri = test_uri
+ self._filename = filename
+ self._test_types = test_types
+ self._test_args = test_args
+ self._single_test_failures = []
+
+ def run(self):
+ proc = StartTestShell(self._binary, self._shell_args + [self._test_uri])
+ self._single_test_failures = ProcessOutput(proc,
+ self._filename,
+ self._test_uri,
+ self._test_types,
+ self._test_args)
+
+ def GetFailures(self):
+ return self._single_test_failures
+
+
+class TestShellThread(threading.Thread):
+
+ def __init__(self, filename_queue, test_shell_binary, test_types,
+ test_args, shell_args, options):
+ """Initialize all the local state for this test shell thread.
+
+ Args:
+ filename_queue: A thread safe Queue class that contains tuples of
+ (filename, uri) pairs.
+ test_shell_binary: The path to test_shell.exe
+ test_types: A list of TestType objects to run the test output against.
+ test_args: A TestArguments object to pass to each TestType.
+ shell_args: Any extra arguments to be passed to test_shell.exe.
+ options: A property dictionary as produced by optparse. The command-line
+ options should match those expected by run_webkit_tests; they
+ are typically passed via the run_webkit_tests.TestRunner class.
+ """
+ threading.Thread.__init__(self)
+ self._filename_queue = filename_queue
+ self._test_shell_binary = test_shell_binary
+ self._test_types = test_types
+ self._test_args = test_args
+ self._test_shell_proc = None
+ self._shell_args = shell_args
+ self._options = options
+ self._failures = {}
+
+ if self._options.run_singly:
+ # When we're running one test per test_shell process, we can enforce
+ # a hard timeout. test_shell uses a default of 10 seconds if no
+ # time-out-ms is given, and the test_shell watchdog uses 2.5x the
+ # test_shell's value. We want to be larger than that.
+ if not self._options.time_out_ms:
+ self._options.time_out_ms = DEFAULT_TEST_TIMEOUT_MS
+ self._time_out_sec = int(self._options.time_out_ms) * 3.0 / 1000.0
+ logging.info("Setting Python per-test timeout to %s ms (%s sec)" %
+ (1000 * self._time_out_sec, self._time_out_sec))
+
+
+ def GetFailures(self):
+ """Returns a dictionary mapping test filename to a list of
+ TestFailures."""
+ return self._failures
+
+ def run(self):
+ """Main work entry point of the thread. Basically we pull urls from the
+ filename queue and run the tests until we run out of urls."""
+ while True:
+ try:
+ filename, test_uri = self._filename_queue.get_nowait()
+ except Queue.Empty:
+ self._KillTestShell()
+ logging.debug("queue empty, quitting test shell thread")
+ return
+
+ # we have a url, run tests
+ if self._options.run_singly:
+ failures = self._RunTestSingly(filename, test_uri)
+ else:
+ failures = self._RunTest(filename, test_uri)
+ if failures:
+ # Check and kill test shell if we need to
+ if len([1 for f in failures if f.ShouldKillTestShell()]):
+ self._KillTestShell()
+ # print the error message(s)
+ error_str = '\n'.join([' ' + f.Message() for f in failures])
+ logging.error("%s failed:\n%s" %
+ (path_utils.RelativeTestFilename(filename), error_str))
+ # Group the errors for reporting
+ self._failures[filename] = failures
+ else:
+ logging.debug(path_utils.RelativeTestFilename(filename) + " passed")
+
+
+ def _RunTestSingly(self, filename, test_uri):
+ """Run a test in a separate thread, enforcing a hard time limit.
+
+ Since we can only detect the termination of a thread, not any internal
+ state or progress, we can only run per-test timeouts when running test
+ files singly.
+ """
+ worker = SingleTestThread(self._test_shell_binary,
+ self._shell_args,
+ test_uri,
+ filename,
+ self._test_types,
+ self._test_args)
+ worker.start()
+ worker.join(self._time_out_sec)
+ if worker.isAlive():
+ # If join() returned with the thread still running, the test_shell.exe is
+ # completely hung and there's nothing more we can do with it. We have
+ # to kill all the test_shells to free it up. If we're running more than
+ # one test_shell thread, we'll end up killing the other test_shells too,
+ # introducing spurious crashes. We accept that tradeoff in order to
+ # avoid losing the rest of this thread's results.
+ logging.error('Test thread hung: killing all test_shells')
+ # PlatformUtility() wants a base_dir, but it doesn't matter here.
+ platform_util = platform_utils.PlatformUtility('')
+ platform_util.KillAllTestShells()
+
+ return worker.GetFailures()
+
+
+ def _RunTest(self, filename, test_uri):
+ """Run a single test file using a shared test_shell process.
+
+ Args:
+ filename: The absolute filename of the test
+ test_uri: The URI version of the filename
+
+ Return:
+ A list of TestFailure objects describing the error.
+ """
+ self._EnsureTestShellIsRunning()
+
+ # Ok, load the test URL...
+ self._test_shell_proc.stdin.write(test_uri + "\n")
+ self._test_shell_proc.stdin.flush()
+
+ # ...and read the response
+ return ProcessOutput(self._test_shell_proc, filename, test_uri,
+ self._test_types, self._test_args)
+
+
+ def _EnsureTestShellIsRunning(self):
+ """Start the shared test shell, if it's not running. Not for use when
+ running tests singly, since those each start a separate test shell in
+ their own thread.
+ """
+ if (not self._test_shell_proc or
+ self._test_shell_proc.poll() is not None):
+ self._test_shell_proc = StartTestShell(self._test_shell_binary,
+ self._shell_args)
+
+ def _KillTestShell(self):
+ """Kill the test shell process if it's running."""
+ if self._test_shell_proc:
+ self._test_shell_proc.stdin.close()
+ self._test_shell_proc.stdout.close()
+ self._test_shell_proc.stderr.close()
+ self._test_shell_proc = None
diff --git a/webkit/tools/layout_tests/layout_package/test_types_unittest.py b/webkit/tools/layout_tests/layout_package/test_types_unittest.py
new file mode 100644
index 0000000..dca5feb
--- /dev/null
+++ b/webkit/tools/layout_tests/layout_package/test_types_unittest.py
@@ -0,0 +1,71 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Unittests that verify that the various test_types (e.g., simplified_diff)
+are working."""
+
+import difflib
+import os
+import unittest
+
+from test_types import simplified_text_diff
+
+class SimplifiedDiffUnittest(unittest.TestCase):
+ def testSimplifiedDiff(self):
+ """Compares actual output with expected output for some test cases. The
+ simplified diff of these test cases should be the same."""
+ test_names = [
+ 'null-offset-parent',
+ 'textAreaLineHeight',
+ 'form-element-geometry',
+ ]
+ differ = simplified_text_diff.SimplifiedTextDiff(None)
+ for prefix in test_names:
+ output_filename = os.path.join(self.GetTestDataDir(),
+ prefix + "-actual-win.txt")
+ expected_filename = os.path.join(self.GetTestDataDir(),
+ prefix + "-expected.txt")
+ output = differ._SimplifyText(open(output_filename).read())
+ expected = differ._SimplifyText(open(expected_filename).read())
+
+ if output != expected:
+ lst = difflib.unified_diff(expected.splitlines(True),
+ output.splitlines(True),
+ 'expected',
+ 'actual')
+ for line in lst:
+ print line.rstrip()
+ self.failUnlessEqual(output, expected)
+
+ def GetTestDataDir(self):
+ return os.path.join(os.path.abspath('testdata'), 'difftests')
+
+if '__main__' == __name__:
+ unittest.main()
diff --git a/webkit/tools/layout_tests/run_webkit_tests.py b/webkit/tools/layout_tests/run_webkit_tests.py
new file mode 100644
index 0000000..e2af53f
--- /dev/null
+++ b/webkit/tools/layout_tests/run_webkit_tests.py
@@ -0,0 +1,653 @@
+#!/bin/env python
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Run layout tests using the test_shell.
+
+This is a port of the existing webkit test script run-webkit-tests.
+
+The TestRunner class runs a series of tests (TestType interface) against a set
+of test files. If a test file fails a TestType, it returns a list TestFailure
+objects to the TestRunner. The TestRunner then aggregates the TestFailures to
+create a final report.
+
+This script reads several files, if they exist in the test_lists subdirectory
+next to this script itself. Each should contain a list of paths to individual
+tests or entire subdirectories of tests, relative to the outermost test
+directory. Entire lines starting with '//' (comments) will be ignored.
+
+For details of the files' contents and purposes, see test_lists/README.
+"""
+
+import glob
+import logging
+import optparse
+import os
+import Queue
+import shutil
+import subprocess
+import sys
+import time
+
+import google.path_utils
+
+from layout_package import compare_failures
+from layout_package import test_expectations
+from layout_package import http_server
+from layout_package import path_utils
+from layout_package import test_failures
+from layout_package import test_shell_thread
+from test_types import image_diff
+from test_types import test_type_base
+from test_types import text_diff
+from test_types import simplified_text_diff
+
+
+# The test list files are found in this subdirectory, which must be a sibling
+# to this script itself.
+TEST_FILE_DIR = 'test_lists'
+
+
+class TestRunner:
+ """A class for managing running a series of tests on a series of test
+ files."""
+
+ # When collecting test cases, we include any file with these extensions.
+ _supported_file_extensions = set(['.html', '.shtml', '.xml', '.xhtml', '.pl',
+ '.php', '.svg'])
+ # When collecting test cases, skip these directories
+ _skipped_directories = set(['.svn', '_svn', 'resources'])
+
+ HTTP_SUBDIR = os.sep.join(['', 'http', ''])
+
+ def __init__(self, options, paths):
+ """Collect a list of files to test.
+
+ Args:
+ options: a dictionary of command line options
+ paths: a list of paths to crawl looking for test files
+ """
+ self._options = options
+
+ self._http_server = http_server.Lighttpd(options.results_directory)
+ # a list of TestType objects
+ self._test_types = []
+ # a set of test files
+ self._test_files = set()
+
+ if options.nosvg:
+ TestRunner._supported_file_extensions.remove('.svg')
+ TestRunner._skipped_directories.add('svg')
+
+ self._GatherTestFiles(paths)
+
+ def __del__(self):
+ sys.stdout.flush()
+ sys.stderr.flush()
+ # Stop the http server.
+ self._http_server.Stop()
+
+ def _GatherTestFiles(self, paths):
+ """Generate a set of test files and place them in self._test_files, with
+ appropriate subsets in self._ignored_failures, self._fixable_failures,
+ and self._fixable_crashes.
+
+ Args:
+ paths: a list of command line paths relative to the webkit/tests
+ directory. glob patterns are ok.
+ """
+ paths_to_walk = set()
+ for path in paths:
+ # If there's an * in the name, assume it's a glob pattern.
+ path = os.path.join(path_utils.LayoutDataDir(), path)
+ if path.find('*') > -1:
+ filenames = glob.glob(path)
+ paths_to_walk.update(filenames)
+ else:
+ paths_to_walk.add(path)
+
+ # Now walk all the paths passed in on the command line and get filenames
+ for path in paths_to_walk:
+ if os.path.isfile(path) and self._HasSupportedExtension(path):
+ self._test_files.add(os.path.normpath(path))
+ continue
+
+ for root, dirs, files in os.walk(path):
+ # don't walk skipped directories and sub directories
+ if os.path.basename(root) in TestRunner._skipped_directories:
+ del dirs[:]
+ continue
+
+ for filename in files:
+ if self._HasSupportedExtension(filename):
+ filename = os.path.join(root, filename)
+ filename = os.path.normpath(filename)
+ self._test_files.add(filename)
+
+ # Filter out http tests if we're not running them.
+ if self._options.nohttp:
+ for path in list(self._test_files):
+ if path.find(self.HTTP_SUBDIR) >= 0:
+ self._test_files.remove(path)
+
+ # Filter and sort out files from the skipped, ignored, and fixable file
+ # lists.
+ saved_test_files = set()
+ if len(self._test_files) == 1:
+ # If there's only one test file, we don't want to skip it, but we do want
+ # to sort it. So we save it to add back to the list later.
+ saved_test_files = self._test_files
+
+ file_dir = os.path.join(os.path.dirname(sys.argv[0]), TEST_FILE_DIR)
+ file_dir = path_utils.GetAbsolutePath(file_dir)
+
+ expectations = test_expectations.TestExpectations(self._test_files,
+ file_dir,
+ self._options.build_type)
+
+ # Remove skipped - both fixable and ignored - files from the
+ # top-level list of files to test.
+ skipped = expectations.GetFixableSkipped() | expectations.GetIgnoredSkipped()
+ self._test_files -= skipped
+
+ # If there was only one test file, run the test even if it was skipped.
+ if len(saved_test_files):
+ self._test_files = saved_test_files
+
+ logging.info('Run: %d tests' % len(self._test_files))
+ logging.info('Skipped: %d tests' % len(skipped))
+ logging.info('Skipped tests do not appear in any of the below numbers\n')
+ logging.info('Deferred: %d tests' % len(expectations.GetFixableDeferred()))
+ logging.info('Expected passes: %d tests' %
+ len(self._test_files -
+ expectations.GetFixable() -
+ expectations.GetIgnored()))
+ logging.info(('Expected failures: %d fixable, %d ignored '
+ 'and %d deferred tests') %
+ (len(expectations.GetFixableFailures()),
+ len(expectations.GetIgnoredFailures()),
+ len(expectations.GetFixableDeferredFailures())))
+ logging.info(('Expected timeouts: %d fixable, %d ignored '
+ 'and %d deferred tests') %
+ (len(expectations.GetFixableTimeouts()),
+ len(expectations.GetIgnoredTimeouts()),
+ len(expectations.GetFixableDeferredTimeouts())))
+ logging.info('Expected crashes: %d fixable tests' %
+ len(expectations.GetFixableCrashes()))
+
+ # Store the expectations in this object to allow it to be used to
+ # track regressions and print results.
+ self._expectations = expectations
+
+ def _HasSupportedExtension(self, filename):
+ """Return true if filename is one of the file extensions we want to run a
+ test on."""
+ extension = os.path.splitext(filename)[1]
+ return extension in TestRunner._supported_file_extensions
+
+ def AddTestType(self, test_type):
+ """Add a TestType to the TestRunner."""
+ self._test_types.append(test_type)
+
+ # We sort the tests so that tests using the http server will run first. We
+ # are seeing some flakiness, maybe related to apache getting swapped out,
+ # slow, or stuck after not serving requests for a while.
+ def TestFilesSort(self, x, y):
+ """Sort with http tests always first."""
+ x_is_http = x.find(self.HTTP_SUBDIR) >= 0
+ y_is_http = y.find(self.HTTP_SUBDIR) >= 0
+ if x_is_http != y_is_http:
+ return cmp(y_is_http, x_is_http)
+ return cmp(x, y)
+
+ def Run(self):
+ """Run all our tests on all our test files.
+
+ For each test file, we run each test type. If there are any failures, we
+ collect them for reporting.
+
+ Return:
+ We return nonzero if there are regressions compared to the last run.
+ """
+ if not self._test_files:
+ return 0
+ start_time = time.time()
+ logging.info("Starting tests")
+
+ # Create the output directory if it doesn't already exist.
+ google.path_utils.MaybeMakeDirectory(self._options.results_directory)
+
+ test_files = list(self._test_files)
+ test_files.sort(self.TestFilesSort)
+ # Create the thread safe queue of (test filenames, test URIs) tuples. Each
+ # TestShellThread pulls values from this queue.
+ filename_queue = Queue.Queue()
+ for test_file in test_files:
+ filename_queue.put((test_file, path_utils.FilenameToUri(test_file)))
+
+ # If we have http tests, the first one will be an http test.
+ if test_files and test_files[0].find(self.HTTP_SUBDIR) >= 0:
+ self._http_server.Start()
+
+ # Instantiate TestShellThreads and start them.
+ threads = []
+ test_shell_binary = path_utils.TestShellBinaryPath(self._options.target)
+ for i in xrange(int(self._options.num_test_shells)):
+ shell_args = []
+ test_args = test_type_base.TestArguments()
+ if self._options.pixel_tests:
+ png_path = os.path.join(self._options.results_directory,
+ "png_result%s.png" % i)
+ shell_args.append("--pixel-tests=" + png_path)
+ test_args.png_path = png_path
+
+ if self._options.new_baseline:
+ test_args.new_baseline = self._options.new_baseline
+ if not self._options.pixel_tests:
+ test_args.text_baseline = True
+
+ # Create separate TestTypes instances for each thread.
+ test_types = []
+ for t in self._test_types:
+ test_types.append(t(self._options.build_type,
+ self._options.results_directory))
+
+ if self._options.startup_dialog:
+ shell_args.append('--testshell-startup-dialog')
+
+ # larger timeout if page heap is enabled.
+ if self._options.time_out_ms:
+ shell_args.append('--time-out-ms=' + self._options.time_out_ms)
+
+ thread = test_shell_thread.TestShellThread(filename_queue,
+ test_shell_binary,
+ test_types,
+ test_args,
+ shell_args,
+ self._options)
+ thread.start()
+ threads.append(thread)
+
+ # Wait for the threads to finish and collect test failures.
+ test_failures = {}
+ for thread in threads:
+ thread.join()
+ test_failures.update(thread.GetFailures())
+
+ print
+ end_time = time.time()
+ logging.info("%f total testing time" % (end_time - start_time))
+
+ # Tests are done running. Compare failures with expected failures.
+ regressions = self._CompareFailures(test_failures)
+
+ # Write summaries to stdout.
+ self._PrintResults(test_failures)
+
+ # Write the summary to disk (results.html) and maybe open the test_shell
+ # to this file.
+ wrote_results = self._WriteResultsHtmlFile(test_failures, regressions)
+ if not self._options.noshow_results and wrote_results:
+ self._ShowResultsHtmlFile()
+
+ sys.stdout.flush()
+ sys.stderr.flush()
+ return len(regressions)
+
+ def _PrintResults(self, test_failures):
+ """Print a short summary to stdout about how many tests passed.
+
+ Args:
+ test_failures is a dictionary mapping the test filename to a list of
+ TestFailure objects if the test failed
+ """
+
+ failure_counts = {}
+ deferred_counts = {}
+ fixable_counts = {}
+ non_ignored_counts = {}
+ fixable_failures = set()
+ deferred_failures = set()
+ non_ignored_failures = set()
+
+ # Aggregate failures in a dictionary (TestFailure -> frequency),
+ # with known (fixable and ignored) failures separated out.
+ def AddFailure(dictionary, key):
+ if key in dictionary:
+ dictionary[key] += 1
+ else:
+ dictionary[key] = 1
+
+ for test, failures in test_failures.iteritems():
+ for failure in failures:
+ AddFailure(failure_counts, failure.__class__)
+ if self._expectations.IsFixable(test):
+ AddFailure(fixable_counts, failure.__class__)
+ fixable_failures.add(test)
+ if self._expectations.IsDeferred(test):
+ AddFailure(deferred_counts, failure.__class__)
+ deferred_failures.add(test)
+ if (not self._expectations.IsIgnored(test) and
+ not self._expectations.IsDeferred(test)):
+ AddFailure(non_ignored_counts, failure.__class__)
+ non_ignored_failures.add(test)
+
+ # Print summaries.
+ print "-" * 78
+
+ # Print breakdown of tests we need to fix and want to pass.
+ # Include skipped fixable tests in the statistics.
+ skipped = (self._expectations.GetFixableSkipped() -
+ self._expectations.GetFixableSkippedDeferred())
+
+ self._PrintResultSummary("=> Tests to be fixed for the current release",
+ self._expectations.GetFixable(),
+ fixable_failures,
+ fixable_counts,
+ skipped)
+
+ self._PrintResultSummary("=> Tests we want to pass for the current release",
+ (self._test_files -
+ self._expectations.GetIgnored() -
+ self._expectations.GetFixableDeferred()),
+ non_ignored_failures,
+ non_ignored_counts,
+ skipped)
+
+ self._PrintResultSummary("=> Tests to be fixed for a future release",
+ self._expectations.GetFixableDeferred(),
+ deferred_failures,
+ deferred_counts,
+ self._expectations.GetFixableSkippedDeferred())
+
+ # Print breakdown of all tests including all skipped tests.
+ skipped |= self._expectations.GetIgnoredSkipped()
+ self._PrintResultSummary("=> All tests",
+ self._test_files,
+ test_failures,
+ failure_counts,
+ skipped)
+ print
+
+ def _PrintResultSummary(self, heading, all, failed, failure_counts, skipped):
+ """Print a summary block of results for a particular category of test.
+
+ Args:
+ heading: text to print before the block, followed by the total count
+ all: list of all tests in this category
+ failed: list of failing tests in this category
+ failure_counts: dictionary of (TestFailure -> frequency)
+ """
+ total = len(all | skipped)
+ print "\n%s (%d):" % (heading, total)
+ skip_count = len(skipped)
+ pass_count = total - skip_count - len(failed)
+ self._PrintResultLine(pass_count, total, "Passed")
+ self._PrintResultLine(skip_count, total, "Skipped")
+ # Sort the failure counts and print them one by one.
+ sorted_keys = sorted(failure_counts.keys(),
+ key=test_failures.FailureSort.SortOrder)
+ for failure in sorted_keys:
+ self._PrintResultLine(failure_counts[failure], total, failure.Message())
+
+ def _PrintResultLine(self, count, total, message):
+ if count == 0: return
+ print ("%(count)d test case%(plural)s (%(percent).1f%%) %(message)s" %
+ { 'count' : count,
+ 'plural' : ('s', '')[count == 1],
+ 'percent' : float(count) * 100 / total,
+ 'message' : message })
+
+ def _CompareFailures(self, test_failures):
+ """Determine how the test failures from this test run differ from the
+ previous test run and print results to stdout and a file.
+
+ Args:
+ test_failures is a dictionary mapping the test filename to a list of
+ TestFailure objects if the test failed
+
+ Return:
+ A set of regressions (unexpected failures, hangs, or crashes)
+ """
+ cf = compare_failures.CompareFailures(self._test_files,
+ test_failures,
+ self._expectations)
+
+ if not self._options.nocompare_failures: cf.PrintRegressions()
+ return cf.GetRegressions()
+
+ def _WriteResultsHtmlFile(self, test_failures, regressions):
+ """Write results.html which is a summary of tests that failed.
+
+ Args:
+ test_failures: a dictionary mapping the test filename to a list of
+ TestFailure objects if the test failed
+ regressions: a set of test filenames that regressed
+
+ Returns:
+ True if any results were written (since expected failures may be omitted)
+ """
+ # test failures
+ if self._options.full_results_html:
+ test_files = test_failures.keys()
+ else:
+ test_files = list(regressions)
+ if not len(test_files):
+ return False
+
+ out_filename = os.path.join(self._options.results_directory,
+ "results.html")
+ out_file = open(out_filename, 'w')
+ # header
+ if self._options.full_results_html:
+ h2 = "Test Failures"
+ else:
+ h2 = "Unexpected Test Failures"
+ out_file.write("<html><head><title>Layout Test Results (%(time)s)</title>"
+ "</head><body><h2>%(h2)s (%(time)s)</h2>\n"
+ % {'h2': h2, 'time': time.asctime()})
+
+ test_files.sort()
+ for test_file in test_files:
+ if test_file in test_failures: failures = test_failures[test_file]
+ else: failures = [] # unexpected passes
+ out_file.write("<p><a href='%s'>%s</a><br />\n"
+ % (path_utils.FilenameToUri(test_file),
+ path_utils.RelativeTestFilename(test_file)))
+ for failure in failures:
+ out_file.write("&nbsp;&nbsp;%s<br/>"
+ % failure.ResultHtmlOutput(
+ path_utils.RelativeTestFilename(test_file)))
+ out_file.write("</p>\n")
+
+ # footer
+ out_file.write("</body></html>\n")
+ return True
+
+ def _ShowResultsHtmlFile(self):
+ """Launches the test shell open to the results.html page."""
+ results_filename = os.path.join(self._options.results_directory,
+ "results.html")
+ subprocess.Popen([path_utils.TestShellBinaryPath(self._options.target),
+ path_utils.FilenameToUri(results_filename)])
+
+
+def ReadTestFiles(files):
+ tests = []
+ for file in files:
+ for line in open(file):
+ line = test_expectations.StripComments(line)
+ if line: tests.append(line)
+ return tests
+
+
+def main(options, args):
+ """Run the tests. Will call sys.exit when complete.
+
+ Args:
+ options: a dictionary of command line options
+ args: a list of sub directories or files to test
+ """
+ # Set up our logging format.
+ log_level = logging.INFO
+ if options.verbose:
+ log_level = logging.DEBUG
+ logging.basicConfig(level=log_level,
+ format='%(asctime)s %(filename)s:%(lineno)-3d'
+ ' %(levelname)s %(message)s',
+ datefmt='%y%m%d %H:%M:%S')
+
+ if not options.target:
+ if options.debug:
+ options.target = "Debug"
+ else:
+ options.target = "Release"
+
+ if (options.pixel_tests and
+ options.build_type != 'v8' and
+ not options.new_baseline):
+ logging.warn('Pixel tests disabled: no expected results for %s builds' %
+ options.build_type)
+ options.pixel_tests = False
+
+ if options.results_directory.startswith("/"):
+ # Assume it's an absolute path and normalize
+ options.results_directory = path_utils.GetAbsolutePath(
+ options.results_directory)
+ else:
+ # If it's a relative path, make the output directory relative to Debug or
+ # Release.
+ basedir = path_utils.WebKitRoot()
+ basedir = os.path.join(basedir, options.target)
+
+ options.results_directory = path_utils.GetAbsolutePath(
+ os.path.join(basedir, options.results_directory))
+
+ logging.info("Using expected results from %s" %
+ path_utils.CustomExpectedResultsDir(options.build_type))
+ logging.info("Placing test results in %s" % options.results_directory)
+ logging.info("Using %s build at %s" % (options.target,
+ path_utils.TestShellBinaryPath(options.target)))
+ if options.pixel_tests:
+ logging.info("Running pixel tests")
+
+ if 'cygwin' == sys.platform:
+ logging.warn("#" * 40)
+ logging.warn("# UNEXPECTED PYTHON VERSION")
+ logging.warn("# This script should be run using the version of python")
+ logging.warn("# in third_party/python_24/")
+ logging.warn("#" * 40)
+ sys.exit(1)
+
+ # Delete the disk cache if any to ensure a clean test run.
+ cachedir = os.path.split(path_utils.TestShellBinaryPath(options.target))[0]
+ cachedir = os.path.join(cachedir, "cache")
+ if os.path.exists(cachedir):
+ shutil.rmtree(cachedir)
+
+ # Include all tests if none are specified.
+ paths = []
+ if args:
+ paths += args
+ if options.test_list:
+ paths += ReadTestFiles(options.test_list)
+ if not paths:
+ paths = ['.']
+ test_runner = TestRunner(options, paths)
+ test_runner.AddTestType(text_diff.TestTextDiff)
+ test_runner.AddTestType(simplified_text_diff.SimplifiedTextDiff)
+ if options.pixel_tests:
+ test_runner.AddTestType(image_diff.ImageDiff)
+ has_new_failures = test_runner.Run()
+ logging.info("Exit status: %d" % has_new_failures)
+ sys.exit(has_new_failures)
+
+if '__main__' == __name__:
+ option_parser = optparse.OptionParser()
+ option_parser.add_option("", "--nohttp", action="store_true", default=False,
+ help="disable http tests")
+ option_parser.add_option("", "--nosvg", action="store_true", default=False,
+ help="disable svg tests")
+ option_parser.add_option("", "--pixel-tests", action="store_true",
+ default=False,
+ help="enable pixel-to-pixel PNG comparisons")
+ option_parser.add_option("", "--results-directory",
+ default="layout-test-results",
+ help="Output results directory source dir,"
+ " relative to Debug or Release")
+ option_parser.add_option("", "--new-baseline", default=None, metavar="DIR",
+ help="save results as new baselines into this "
+ "directory (e.g. layout_test_results/v8), "
+ "overwriting whatever's already there. "
+ "If pixel tests are being run, only image "
+ "baselines will be saved, not text.")
+ option_parser.add_option("", "--noshow-results", action="store_true",
+ default=False, help="don't launch the test_shell"
+ " with results after the tests are done")
+ option_parser.add_option("", "--full-results-html", action="store_true",
+ default=False, help="show all failures in"
+ "results.html, rather than only regressions")
+ option_parser.add_option("", "--num-test-shells",
+ default=1,
+ help="The number of test shells to run in"
+ " parallel. EXPERIMENTAL.")
+ option_parser.add_option("", "--save-failures", action="store_true",
+ default=False,
+ help="Save lists of expected failures and crashes "
+ "and use them in computing regressions.")
+ option_parser.add_option("", "--nocompare-failures", action="store_true",
+ default=False,
+ help="Disable comparison to the last test run. "
+ "When enabled, show stats on how many tests "
+ "newly pass or fail.")
+ option_parser.add_option("", "--time-out-ms",
+ default=None,
+ help="Set the timeout for each test")
+ option_parser.add_option("", "--run-singly", action="store_true",
+ default=False,
+ help="run a separate test_shell for each test")
+ option_parser.add_option("", "--debug", action="store_true", default=False,
+ help="use the debug binary instead of the release "
+ "binary")
+ option_parser.add_option("", "--build-type", default="v8",
+ help="use these test lists and expected results "
+ "('kjs' or 'v8')")
+ option_parser.add_option("", "--target", default="",
+ help="Set the build target configuration (overrides"
+ "--debug)")
+ option_parser.add_option("-v", "--verbose", action="store_true",
+ default=False, help="include debug level logging")
+ option_parser.add_option("", "--startup-dialog", action="store_true",
+ default=False,
+ help="create a dialog on test_shell.exe startup")
+ option_parser.add_option("", "--test-list", action="append",
+ help="read list of tests to run from file",
+ metavar="FILE")
+ options, args = option_parser.parse_args()
+ main(options, args)
diff --git a/webkit/tools/layout_tests/run_webkit_tests.sh b/webkit/tools/layout_tests/run_webkit_tests.sh
new file mode 100755
index 0000000..6ac6696
--- /dev/null
+++ b/webkit/tools/layout_tests/run_webkit_tests.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+system_root=`cygpath "$SYSTEMROOT"`
+export PATH="/usr/bin:$system_root/system32:$system_root:$system_root/system32/WBEM"
+
+exec_dir=$(dirname $0)
+
+"$exec_dir/../../../third_party/python_24/python.exe" \
+ "$exec_dir/run_webkit_tests.py" "$@"
diff --git a/webkit/tools/layout_tests/test_lists/README b/webkit/tools/layout_tests/test_lists/README
new file mode 100644
index 0000000..985ebe2
--- /dev/null
+++ b/webkit/tools/layout_tests/test_lists/README
@@ -0,0 +1,34 @@
+The files in this directory are read by the
+run_webkit_tests.py script and used to determine which tests to run
+and which failures to consider regressions.
+
+If we *never* expect to pass these tests (e.g. test for Apple's objective-c
+API), then add them to tests_ignore.txt. If we expect that we might ever want to
+pass the test, first file a bug, then add it to tests_fixable.txt.
+
+Tests can have the following metatdata associated with them (optional):
+DEFER : We don't expect to pass them in the current release.
+SKIP : We don't want to run them (perhaps because they take too long).
+
+Tests have a build-type (required):
+V8 # The test only fails in V8 build.
+KJS # The test only fails in KJS build.
+
+Tests can also have expections (required):
+PASS
+FAIL
+TIMEOUT
+CRASH
+
+The format of a test is as follows:
+BUILD_TYPE # METADATA : TEST = EXPECTATIONS
+
+For example
+V8 # DEFER : LayoutTests/media = PASS | FAIL
+
+The above means that in the V8 build, all the media tests are flaky and
+we'll defer fixing them for a future release.
+
+Note that tests_fixable.txt and tests_ignored.txt aren't allowed to share any
+lines. Except for skipped tests, all tests are run. In calculating success
+metrics, we ignore tests in tests_ignored.txt and deferred tests.
diff --git a/webkit/tools/layout_tests/test_lists/tests_fixable.txt b/webkit/tools/layout_tests/test_lists/tests_fixable.txt
new file mode 100644
index 0000000..17ce386
--- /dev/null
+++ b/webkit/tools/layout_tests/test_lists/tests_fixable.txt
@@ -0,0 +1,718 @@
+// These tests are expected to fail until we get around to fixing
+// them.
+
+
+// -----------------------------------------------------------------
+// DEBUG ONLY FAILURES!
+// -----------------------------------------------------------------
+
+// Bug 1124548: Copying with no selection is sometimes supposed to work
+// This test also crashes in debug due to an ASSERT. (see bug 1058654)
+V8 | KJS # DEFER : LayoutTests/editing/execCommand/copy-without-selection.html = FAIL | CRASH
+
+// -----------------------------------------------------------------
+// HANGING TESTS
+// -----------------------------------------------------------------
+
+// onload race condition due to poorly designed test.
+// Works fine when run stand-alone. Not needed for Beta.
+V8 | KJS # DEFER : LayoutTests/fast/dom/frame-loading-via-document-write.html = FAIL
+
+// -----------------------------------------------------------------
+// FLAKY TESTS
+// -----------------------------------------------------------------
+
+// This test uses a -webkit-transition-duration and a set timeout, probably
+// just a small race in our timers. Fails once in a while, only on v8.
+V8 # DEFER : LayoutTests/fast/css/transition-color-unspecified.html = PASS | FAIL
+
+// Flaky tests, see bug 877986.
+// WebKit's CSS counters are somewhat broken, thus expected results are failures
+// Our high-precision timers make these tests flakey.
+// We could fork these tests, but we'll just unfork them as soon as
+// our high-precision timers are public.
+V8 | KJS # DEFER : LayoutTests/css2.1/t1204-increment-00-c-o.html = FAIL | PASS
+V8 | KJS # DEFER : LayoutTests/css2.1/t1204-increment-01-c-o.html = FAIL | PASS
+V8 | KJS # DEFER : LayoutTests/css2.1/t1204-increment-02-c-o.html = FAIL | PASS
+V8 | KJS # DEFER : LayoutTests/css2.1/t1204-reset-00-c-o.html = FAIL | PASS
+V8 | KJS # DEFER : LayoutTests/css2.1/t1204-reset-01-c-o.html = FAIL | PASS
+
+// Bug 1143337
+// These tests are here because they fail on the buildbot, but not locally.
+// Seems to be due to one or more timing issues in the tests.
+// These only timeout on the v8-Debug buildbot it seems. (eseidel, 4/28)
+// I'm not seeing this fail locally in v8-Debug or v8-Release (eseidel, 4/25)
+V8 | KJS # LayoutTests/http/tests/security/dataURL/xss-DENIED-to-data-url-in-foreign-domain-subframe-location-change.html = PASS | FAIL
+V8 | KJS # LayoutTests/http/tests/security/dataURL/xss-DENIED-from-data-url-in-foreign-domain-subframe.html = PASS | TIMEOUT
+
+// This are failing for different reasons under our new lighttpd configuration
+// TODO(deanm): Address all of these via lighttpd if possible, otherwise fork.
+// Maybe flaky and need to be forked? Bug 1234761.
+
+// Consistently fails on KJS only
+KJS # LayoutTests/http/tests/security/cross-frame-access-call.html = FAIL
+// Maybe flaky and need to be forked?
+V8 | KJS # LayoutTests/http/tests/security/cross-frame-access-enumeration.html = TIMEOUT
+// Difference in caching headers
+V8 | KJS # LayoutTests/http/tests/xmlhttprequest/cache-override.html = FAIL
+// LightTPD doesn't accept unknown HTTP methods
+V8 | KJS # LayoutTests/http/tests/xmlhttprequest/methods-lower-case.html = TIMEOUT
+V8 | KJS # LayoutTests/http/tests/xmlhttprequest/methods-async.html = TIMEOUT
+// LightTPD doesn't accept unknown HTTP methods and passes CGIs a Content-Type
+// even when a request didn't send the header.
+V8 | KJS # LayoutTests/http/tests/xmlhttprequest/methods.html = FAIL
+
+// -----------------------------------------------------------------
+// TEXT
+// -----------------------------------------------------------------
+
+// This class of test fails because of size differences in text runs.
+// Mostly this is because of international text rendering differences.
+
+// Bug 1124513: the max length is being applied correctly, but the over- and
+// under-lines aren't placed properly over the "x".
+// The under-lines are a cosmetic error which is not necessary to fix for Beta. (eseidel)
+V8 | KJS # DEFER : LayoutTests/fast/forms/input-text-maxlength.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/forms/input-text-paste-maxlength.html = FAIL
+
+// Font differences, requiring overriden metrics, not a real bug, not fixing for Beta
+V8 | KJS # DEFER : LayoutTests/fast/text/international/bidi-AN-after-L.html = FAIL
+
+// Bug: 1145880
+// Parethesis missing, metrics wrong.
+V8 | KJS # DEFER : LayoutTests/fast/text/international/bidi-neutral-run.html = FAIL
+
+// Bug: 628529: complex text effects
+// This is a real bug, but not one we're fixing for Beta.
+V8 | KJS # DEFER : LayoutTests/fast/text/stroking-decorations.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/text/stroking.html = FAIL
+
+// Bug: 1124522
+// Incrorect results, in incorrect international font metrics.
+// Fixing these overrides does not help us to Beta, deffering
+V8 | KJS # DEFER : LayoutTests/fast/text/atsui-multiple-renderers.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/text/atsui-pointtooffset-calls-cg.html = FAIL
+
+// Bug: 1143381
+// This test checks that we hack around a bug in helvetica. We fail to.
+V8 | KJS # DEFER : LayoutTests/fast/text/wide-zero-width-space.html = FAIL
+
+// Font-size differences in international text cause the wrong character
+// to be under the (x,y) click location used by the test. See bug 850411
+// on faking international font sizes like we do for Latin fonts.
+V8 | KJS # DEFER : LayoutTests/fast/text/atsui-rtl-override-selection.html = FAIL
+
+// Bug: 1124542
+// More missing international text overides, not needed for Beta.
+// Capitalization results match Safari, even if "not fully correct"
+V8 | KJS # DEFER : LayoutTests/fast/text/capitalize-boundaries.html = FAIL
+
+// Bug: 1145887
+// Different button line-heights, our behavior looks wrong.
+V8 | KJS # DEFER : LayoutTests/fast/forms/control-restrict-line-height.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/replaced/table-percent-height.html = FAIL
+
+// Bug 992930: Unable to load file:/// URLs from data: URLs.
+V8 | KJS # DEFER : LayoutTests/fast/events/standalone-image-drag-to-editable.html = FAIL
+
+// Bug 1187672. Two font faces should be identical but aren't. Punting SVG.
+V8 | KJS # DEFER : LayoutTests/svg/custom/font-face-simple.svg = FAIL
+
+// -----------------------------------------------------------------
+// URL
+// -----------------------------------------------------------------
+
+// http://b/1089231: Form submission (GET) on non-standard url does not append a query.
+// Defering these tests as the expected behavior is wonky, and shouldn't affect
+// existing apps one way or another.
+
+// Implicit expectation in this test is that you can "set query" on a data URL,
+// and it should replace the first "?" substring. This makes absolutely no sense.
+V8 | KJS # DEFER : LayoutTests/fast/events/stopPropagation-submit.html = FAIL
+
+// Expected results has a terminal "?", since "set query" on about:blank is allowed.
+// This is strange since query should have no meaning in non-standard urls
+V8 | KJS # DEFER : LayoutTests/http/tests/navigation/onload-navigation-iframe-timeout.html = FAIL
+V8 | KJS # DEFER : LayoutTests/http/tests/navigation/onload-navigation-iframe.html = FAIL
+
+// -----------------------------------------------------------------
+// Other
+// -----------------------------------------------------------------
+
+// Bug 865472, this should just need proper pixel test rebaselining.
+V8 # LayoutTests/http/tests/navigation/javascriptlink-frames.html = FAIL
+
+// Bug 1235433, javascript can execute before stylesheets are completely loaded.
+V8 | KJS # DEFER : LayoutTests/http/tests/local/stylesheet-and-script-load-order.html = FAIL
+
+// Bug 1195064, dragging into a textarea is less-ideal as it used to be.
+V8 | KJS # DEFER : LayoutTests/fast/forms/drag-into-textarea.html = FAIL
+
+// Bug: 1143492
+// Window status should always return a string object
+// WebKit does this to match IE, FF also fails this test.
+// Obscure, not sure we care. DEFER for Beta
+V8 | KJS # DEFER : LayoutTests/fast/dom/assign-to-window-status.html = FAIL
+
+// Bug 905894
+// Getting parseerror (probably wrong svn:eol-style)
+// Will be fixed by upstream merge
+V8 | KJS # DEFER : LayoutTests/fast/xsl/xslt-enc16.xml = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/xsl/xslt-enc16to16.xml = FAIL
+
+// Bug: 742182, 845388
+// Mac Safari under certain circumstances automatically places
+// a caret in editable document even when none was requested programatically.
+// We don't intend to copy this feature (at least not for Beta).
+V8 | KJS # DEFER : LayoutTests/editing/selection/designmode-no-caret.html = FAIL
+
+// Bug: 742182, 845388, 960092
+// Platform-specific: simulates command-{arrow} input to modify selection
+// Our Event-Sender isn't robust enough to support this.
+// Not required for Beta. This may also be related to known home/end issues
+// which are intended to be fixed for Beta.
+V8 | KJS # DEFER : LayoutTests/editing/selection/move-begin-end.html = FAIL
+
+// Bug 845400 Miscellaneous layout issues under editing
+V8 | KJS # DEFER : LayoutTests/editing/pasteboard/copy-standalone-image.html = FAIL
+
+// Bug 845400
+// The end result looks right, but the event messages differ.
+// Not critical for Beta, DEFER
+V8 | KJS # DEFER : LayoutTests/editing/pasteboard/paste-xml.xhtml = FAIL
+
+// Bug 849441
+// Directionality of mixed-direction text in selected choice should
+// match that in the <select> option lists.
+// Low priority, unclear if test expectations are correct (see bug)
+V8 | KJS # DEFER : LayoutTests/fast/forms/select-writing-direction-natural.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/text/international/bidi-menulist.html = FAIL
+
+// Bug 850875
+// requires support for layoutTestController.encodeHostName()
+// Not critical for Beta, DEFER
+V8 | KJS # DEFER : LayoutTests/fast/encoding/idn-security.html = FAIL
+
+// Bug 852346
+// Tests link coloring and needs a history dataLayoutTests.
+// This is a test tool problem, not a Chrome problem.
+// Not critical for Beta. DEFER
+V8 | KJS # DEFER : LayoutTests/fast/history/clicked-link-is-visited.html = FAIL
+
+// Bug 1027226
+// Bug 945322: test shell should dump text when
+// layoutTestController.notifyDone() is called
+// Not critical for beta.
+V8 | KJS # DEFER : LayoutTests/editing/selection/drag-in-iframe.html = TIMEOUT
+
+// BUG 938563: occasionally times out (performs about 50 HTTP CGI requests)
+V8 | KJS # DEFER : LayoutTests/http/tests/xmlhttprequest/supported-xml-content-types.html = PASS | TIMEOUT
+
+// Bug 849056
+// We don't support NPN_Enumerate, but don't know of any plugin
+// which depends on that functionality. So we ignore this for beta.
+V8 | KJS # DEFER : LayoutTests/plugins/netscape-enumerate.html = FAIL
+
+// Bug: 767628
+// This fails due to scrolling and event differences.
+V8 | KJS # DEFER : LayoutTests/fast/forms/focus-selection-textarea.html = FAIL
+
+// This tests the screen's pixel depth, which we don't set on the buildbots
+// so it depends on the users settings. Making this a broken test for us.
+// The test must be fixed to not depend on user settings and rebaselined. post-beta.
+V8 | KJS # DEFER : LayoutTests/fast/dom/Window/window-screen-properties.html = FAIL
+
+// Bug: 849060
+// Plugin creation is delayed until after first layout, so
+// setwindow isn't being called.
+V8 | KJS # LayoutTests/plugins/netscape-plugin-setwindow-size.html = FAIL
+
+// gc-6.html failed because the loop in the test didn't allocate enough
+// garbage objects to trigger a GC. It was passing before. The code
+// for triggering GC is unreliable.
+// Not a useful test for us, DEFER
+V8 | KJS # DEFER : LayoutTests/fast/dom/gc-6.html = TIMEOUT
+
+// Bug: 894476
+// It is flaky on V8 build, we need to investigate it.
+// It fails on KJS build. It is not something for beta.
+KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-put.html = FAIL
+// It is flaky on V8 build.
+V8 # LayoutTests/http/tests/security/cross-frame-access-put.html = PASS | FAIL
+
+// V8 specific test
+KJS # SKIP | DEFER : chrome/fast/dom/script_lineno.html = FAIL
+
+// KJS doesn't support cross-domain setting of window.opener.
+KJS # DEFER : chrome/http/tests/misc/set-window-opener-to-null.html = FAIL
+
+// Bug: 1135526
+// I've not seen the failing results, so it's difficult to guess what might be wrong
+// This test flips back and forth on the bots, passes locally (eseidel, 4/28)
+// This test uses setTimeout(foo, 1) to poll window.closed after window.close() is
+// called to only continue once the window is fully closed. It's possible we're
+// setting window.close too early (wild guess).
+// only failing on KJS hence removing V8 (sandholm, 4/29)
+// Defer until after beta since it only fails in KJS.
+KJS # DEFER : LayoutTests/fast/dom/Window/new-window-opener.html = FAIL
+
+// Bug 982602
+// We don't support support window.resizeTo (nor is it planned for Beta)
+V8 | KJS # DEFER : LayoutTests/fast/dom/Window/window-resize-and-move-arguments.html = FAIL
+
+// layoutTestController.setPopupBlockingEnabled() does not exist.
+// Not critical for Beta.
+V8 | KJS # DEFER : LayoutTests/fast/events/open-window-from-another-frame.html = FAIL
+
+// Test expects that when focus is in an iframe and page-up is hit, the parent
+// document is also scrolled
+// IE and FF also "fail" this test. DEFER
+V8 | KJS # DEFER : LayoutTests/fast/frames/iframe-scroll-page-up-down.html = FAIL
+
+// Bug 1082426
+// document.write() pf plain text does not always flush
+// This is a known WebKit bug, https://bugs.webkit.org/show_bug.cgi?id=8961
+V8 | KJS # DEFER : LayoutTests/editing/execCommand/delete-no-scroll.html = FAIL
+
+// TODO: investigate. Broken with webkit merge 28723:29478
+// KJS only, so we don't care for Beta.
+KJS # DEFER : LayoutTests/http/tests/security/frameNavigation/xss-DENIED-plugin-navigation.html = FAIL
+
+// Bug: 879449
+// TODO(joshia): Need some changes to the test shell in order to support
+// Java applet related unit tests. So disable the following for now.
+// These tests should be fixed immediately after the Java applets work is done.
+V8 | KJS # LayoutTests/fast/replaced/applet-disabled-positioned.html = FAIL
+V8 | KJS # LayoutTests/fast/replaced/applet-rendering-java-disabled.html = FAIL
+
+// Bug 1198880
+V8 | KJS # DEFER : LayoutTests/svg/custom/svgsvgelement-ctm.xhtml = FAIL
+
+// Bug 1204878
+V8 | KJS # LayoutTests/http/tests/navigation/post-goback1.html = FAIL
+
+// -----------------------------------------------------------------
+// PENDING TESTS (forked to pending/, need to be sent upstream)
+// -----------------------------------------------------------------
+
+// BUG 792023. See http://bugs.webkit.org/show_bug.cgi?id=15690 and 16494
+// Fixed tests are in pending directory. (The originals still pass consistently
+// in KJS.)
+V8 # DEFER : LayoutTests/dom/html/level2/html/HTMLFrameElement09.html = FAIL
+V8 # DEFER : LayoutTests/dom/html/level2/html/HTMLIFrameElement11.html = FAIL
+
+// Bug 972450: These tests don't work with fast timers due to setTimeout
+// races. Pending versions have these fixed.
+V8 | KJS # DEFER : LayoutTests/fast/history/history_reload.html = PASS | FAIL
+V8 | KJS # DEFER : LayoutTests/fast/repaint/bugzilla-6473.html = PASS | FAIL
+
+// Bug 982608: test had a wrong result for one condition
+V8 | KJS # DEFER : LayoutTests/plugins/destroy-stream-twice.html = FAIL
+
+// This test has been modified and placed in pending, so we ignore the original
+// until we get our modification into WebKit.
+V8 | KJS # DEFER : LayoutTests/security/block-test.html = PASS | FAIL
+
+// Bug 1124522
+// Test forked into pending and fixed.
+V8 # DEFER : LayoutTests/fast/js/function-toString-parentheses.html = FAIL
+
+// Bug 1132721. Forked to pending/fast/encoding/script-in-head.html
+// Should get this change pushed upstream and then unfork.
+// Stopped failing
+// V8 # DEFER : LayoutTests/fast/encoding/script-in-head.html = PASS | FAIL | TIMEOUT
+
+// Bug 1143337. Forked to pending/http/tests/security/.
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-child-explicit-domain.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-parent-explicit-domain.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-port-explicit-domain.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-port.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-protocol-explicit-domain.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/cross-frame-access-protocol.html = PASS | FAIL | TIMEOUT
+V8 | KJS # DEFER : LayoutTests/http/tests/security/protocol-compare-case-insensitive.html = PASS | FAIL | TIMEOUT
+
+// Bug 1199617. Forked to pending/svg/carto.net/window.svg.
+// Test did not wait for all created functions to be called via
+// setTimeout.
+V8 | KJS # DEFER : LayoutTests/svg/carto.net/window.svg = PASS | FAIL
+
+// Bug 1064038. Image with border="1" drawn without the border.
+V8 | KJS # DEFER : pending/fast/forms/image-border.html = FAIL
+
+// Bug 1055396. Vertical scrollbar created when there is no overflow.
+V8 | KJS # DEFER : pending/fast/forms/textarea-scrollbar-height.html = FAIL
+
+// Bug 1059184. Dashed border-right isn't drawn on tall elements.
+V8 | KJS # DEFER : pending/css/border-height.html = FAIL
+
+// -----------------------------------------------------------------
+// DEFERRED TESTS (deferred until a future release)
+// -----------------------------------------------------------------
+
+// Bug 1203341: Requires a working postMessage implementation
+V8 # DEFER : LayoutTests/http/tests/security/cross-frame-access-delete.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/security/cross-frame-access-history-put.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/security/cross-frame-access-location-put.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/security/postMessage/domain-and-uri-unaffected-by-base-tag.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/security/postMessage/domain-unaffected-by-document-domain.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/security/postMessage/javascript-page-still-sends-domain.html = TIMEOUT
+V8 # DEFER : LayoutTests/http/tests/messaging/cross-domain-message-send.html = TIMEOUT
+
+// Bug 1135948: Fails because we cannot call plugins as functions.
+V8 # DEFER : LayoutTests/plugins/bindings-test.html = FAIL
+
+// Bug 1124435: deal with the deletion UI in a later release.
+V8 | KJS # DEFER : LayoutTests/editing/deleting/deletionUI-single-instance.html = FAIL
+
+// Bug 871718: This test loads data: URLs into frames and sets queries on then.
+// This is totally broken. This layout test should be rewitten so that the
+// subframes are not data URLs (probably we want files in the resources dir.).
+V8 | KJS # DEFER : LayoutTests/fast/encoding/char-encoding.html = TIMEOUT
+
+// Bug 1130795: since we don't have Aqua-themed controls, don't ignore the
+// box-shadow properties of controls that request Aqua theming. But since Aqua
+// controls are rare on the web, defer this fix.
+V8 | KJS # DEFER : LayoutTests/fast/forms/box-shadow-override.html = FAIL
+
+// These tests are not valid: the so-called expected results are not known to
+// be correct. See bug 849072.
+// TODO(ojan): They are *our* tests.
+// It seems silly to skip our own tests when we can change/delete them.
+// I'm marking them as deferred for now, but we should do something with them.
+V8 | KJS # DEFER | SKIP : chrome/http/mime = PASS
+
+// Bug: 916857: These tests fail because of <audio> and <video>?
+// Removed from the skip-list since they consistently fail quickly.
+V8 | KJS # DEFER : LayoutTests/http/tests/media/video-play-stall.html = FAIL
+V8 | KJS # DEFER : LayoutTests/http/tests/media/video-play-stall-seek.html = FAIL
+V8 | KJS # DEFER : LayoutTests/http/tests/media/video-seekable-stall.html = FAIL
+V8 | KJS # DEFER : LayoutTests/http/tests/media/remove-while-loading.html = FAIL
+
+// We don't support the storage APIs. Some of the them hang.
+V8 | KJS # DEFER | SKIP : LayoutTests/storage = PASS
+
+// Fails due to storage APIs not implemented. See bug 1124568. Might be worth
+// re-baselining temporarily so the rest of the conditions are still tested.
+V8 | KJS # DEFER : LayoutTests/fast/dom/Window/window-function-name-getter-precedence.html = FAIL
+
+// These tests all time out, which makes running the suite take too long if
+// they're included. See bug 916857 to investigate <audio> and <video>.
+V8 | KJS # DEFER | SKIP : LayoutTests/media = TIMEOUT
+
+// Bug 850287: Need better Thai line-breaking. Not a high priority, because
+// it's acceptable as it is.
+V8 | KJS # DEFER : LayoutTests/fast/text/international/thai-line-breaks.html = FAIL
+
+// Bug 941049: Function arguments object is copied for each access.
+V8 # DEFER : LayoutTests/fast/js/kde/function_arguments.html = FAIL
+
+// Bug 1155674: Test sometimes fails on V8 in debug mode, because it's very
+// timing dependent. We should consider rewriting the test case to give us
+// more wriggle room timing wise (especially for debug builds). Fixing the
+// issue now is not going to improve product quality for beta.
+V8 # DEFER : LayoutTests/fast/forms/search-event-delay.html = PASS | FAIL
+
+
+// The following tests (up to the ---- line below) need to add new methods to
+// layoutTestController in test_shell since WebKit add those methods to its
+// layoutTestController in DumpRenderTree tools.
+
+// BUG 973468: Need a setAuthorAndUserStylesEnabled method in
+// layoutTestController. Now we have preference to enable/disable user
+// styles(not work now), we still need to add a preference to enable/disable
+// styles of both author and user.
+// Deferring, we don't support user-controlled UA stylesheets (in beta)
+// Actually, gonna SKIP because it causes an additional error message in:
+// LayoutTests/fast/css/display-none-inline-style-change-crash.html somehow
+// the message is dumped after the #EOF, which causes an additional
+// error in the header of the following test.
+V8 | KJS # SKIP | DEFER : LayoutTests/fast/css/disabled-author-styles.html = FAIL
+
+// ------------------------------------------------------------------------- //
+
+// Bug: 924387, 1058654
+// Broken until we fix our port to support remote TTF fonts and SVG Fonts
+// GDI @font-face support has been implemented upstream, but we don't plan
+// to fork to add support for @font-face for Beta.
+// upstream: http://trac.webkit.org/projects/webkit/changeset/31507
+V8 | KJS # DEFER : LayoutTests/fast/css/font-face-multiple-remote-sources.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/css/font-face-remote.html = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/custom/font-face-cascade-order.svg = FAIL
+
+// Bug: 1007391
+// These hit a not-implemented code-path in @font-face code
+// Fixing this should not be required for beta.
+V8 | KJS # DEFER : LayoutTests/fast/css/font-face-implicit-local-font.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/css/font-face-unicode-range.html = FAIL
+
+// Bug: 1110028
+// The v8 bindings allow shadowing of all properties on the global object. If you use
+// 'var prop = value' you will get a new variable named prop that shadows builtin properties
+// on the global object. This behavior is consistent and I'm reluctant to make the
+// massive change that would be needed to implement the inconsistent handling of this
+// that KJS has (some properties can be shadowed and others can't). This should have
+// low priority.
+// We currently match IE, the plan is to convince KJS to change post-beta. DEFER (eseidel, 4/25)
+V8 # DEFER : LayoutTests/fast/dom/Window/window-property-shadowing-name.html = TIMEOUT
+V8 # DEFER : LayoutTests/fast/js/var-declarations-shadowing.html = FAIL
+
+// This test expects weird behavior of __defineGetter__ on the
+// window object. It expects variables introduced with 'var x = value'
+// to behave differently from variables introduced with 'y = value'.
+// This just seems wrong and should have very low priority.
+// Agreed, not required for Beta, we can debate this with WebKit post Beta, (eseidel, 4/25)
+V8 # DEFER : LayoutTests/fast/dom/getter-on-window-object2.html = FAIL
+
+// Bug: 1042653
+// We don't support WebKit-Editing-Delete-Button
+// We've chosen not to for Beta. DEFER
+V8 | KJS # DEFER : LayoutTests/editing/deleting/5408255.html = FAIL
+
+// Bug: 845337
+// Missing two callbacks:
+// -EDITING DELEGATE: shouldBeginEditingInDOMRange:range ...
+// -EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
+V8 | KJS # LayoutTests/editing/pasteboard/testcase-9507.html = FAIL
+
+// Bug: 1042838
+// User stylesheets not currently supported by chrome.
+// Webkit supports them by doing filesystem operations directly.
+// This is disallowed in a sandboxed renderer. The test fails in test_shell.exe because the
+// necessary filesystem stubs are notImplemented(), and would need to be proxied through the browser
+V8 | KJS # DEFER : LayoutTests/http/tests/security/local-user-CSS-from-remote.html = FAIL
+
+// Extra space at end of test results. Since this is a crash test, a
+// FAIL here is just as good as running the test normally
+// Not sure why it passes (frequently on V8, rarely on KJS). See bug 1126050.
+// FAIL results from an extra newline at the top of the results
+// the checked in results do not include the PASS text
+// fixing this test file to be reliable does not help Beta. DEFERing
+V8 | KJS # DEFER : LayoutTests/http/tests/navigation/changing-frame-hierarchy-in-onload.html = PASS | FAIL
+
+// -----------------------------------------------------------------
+// SVG TESTS
+// -----------------------------------------------------------------
+
+// BUG: 992321
+// SVG layout tests have just been enabled. The failures are listed
+// below, and need to be investigated, categorized, and (one hopes)
+// fixed.
+
+// Keep score here!
+//
+// P: Passes
+// S: Pass simplified diff (probable nonbugs)
+// F: Failures (in simplified as well as full text)
+// X: Crashes/hangs
+// T: Total # of tests
+//
+// (note 5-22-08: there should probably be a column for image diff
+// failures as well. Some of the font tests seem to be flaky and
+// return inconsistent image results.)
+//
+// P S F X T
+// 1-18-08 473 87 125 3 688
+// 1-29-08 492 86 106 4 688
+// 2-05-08 513 97 83 1 694
+// 4-17-08 520 88 85 0 :) 693
+// 4-21-08 526 87 80 0 693
+// 4-22-08 540 138 29 0 707
+// 5-05-08 551 138 15 0 707
+// 5-09-08 554 139 16 0 712
+// 5-16-08 587 111 14 0 712
+// 5-22-08 641 58 7 0 712
+//
+
+// The following tests fail because SVG animation is not yet implemented
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-06-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-07-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-08-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-28-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-30-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-33-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-36-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-37-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-41-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-78-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-80-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-81-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-82-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/animate-elem-83-t.svg = FAIL
+
+// This test fails because SVG filters are not implemented
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/filters-example-01-b.svg = FAIL
+
+// These test fail full text diff (but not simplified diff) most likely due
+// to differing implementations of SVG fonts. They may or may not represent real
+// bugs which need fixin'
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/smallFonts.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textBiDi.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textGlyphOrientationHorizontal.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textOnPath.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textOnPath2.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textOnPath3.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/textOnPathSpaces.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/verticalText.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/batik/text/verticalTextOnPath.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/custom/path-textPath-simulation.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/text/text-fonts-01-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/text/text-intro-05-t.svg = FAIL
+V8 | KJS # DEFER : LayoutTests/svg/text/text-path-01-b.svg = FAIL
+
+// This test is failing because Apple's results appear to be bogus. Will let them know.
+V8 | KJS # DEFER : LayoutTests/svg/custom/gradient-stop-style-change.svg = FAIL
+
+// This test fails because of an oddity in stroke width calculation. A
+// line is stroked horizontally from Y=100 with stroke width 100, we consider
+// it to be occupying the scan lines from Y=50 to Y=149 inclusive, which
+// is a total of 100 lines. Apple expects it to be occupying Y=150 as
+// well. The specification isn't very specific on which behavior is correct,
+// but I feel like ours makes more sense.
+V8 | KJS # DEFER : LayoutTests/svg/custom/stroke-width-click.svg = FAIL
+
+// These tests all pass simplified diff, but fail full text diffs due to
+// positions and/or widths that deviate from Apple's expectations by varying
+// degrees. These are almost certainly nonbugs, but won't be rebased until
+// we can say for sure.
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/extend-namespace-01-f.svg = FAIL // 12 numbers differ, by an absolute total of 73.93
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/fonts-glyph-02-t.svg = FAIL // 1 numbers differ, by an absolute total of 10.00
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/metadata-example-01-b.svg = FAIL // 11 numbers differ, by an absolute total of 1.08
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-01-t.svg = FAIL // 10 numbers differ, by an absolute total of 15.39
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-02-t.svg = FAIL // 20 numbers differ, by an absolute total of 327.17
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-03-f.svg = FAIL // 14 numbers differ, by an absolute total of 58.82
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-10-t.svg = FAIL // 21 numbers differ, by an absolute total of 23.96
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-12-t.svg = FAIL // 8 numbers differ, by an absolute total of 119.28
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/paths-data-15-t.svg = FAIL // 6 numbers differ, by an absolute total of 21.34
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/struct-group-03-t.svg = FAIL // 8 numbers differ, by an absolute total of 3.48
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/text-fonts-01-t.svg = FAIL // 3 numbers differ, by an absolute total of 42.00
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/text-intro-05-t.svg = FAIL // 18 numbers differ, by an absolute total of 237.00
+V8 | KJS # DEFER : LayoutTests/svg/W3C-SVG-1.1/text-path-01-b.svg = FAIL // 16 numbers differ, by an absolute total of 67.92
+V8 | KJS # DEFER : LayoutTests/svg/custom/control-points-for-S-and-T.svg = FAIL // 6 numbers differ, by an absolute total of 31.36
+V8 | KJS # DEFER : LayoutTests/svg/custom/dasharrayOrigin.svg = FAIL // 2 numbers differ, by an absolute total of 0.20
+V8 | KJS # DEFER : LayoutTests/svg/custom/linking-a-03-b-all.svg = FAIL // 4 numbers differ, by an absolute total of 0.06
+V8 | KJS # DEFER : LayoutTests/svg/custom/linking-a-03-b-viewBox-transform.svg = FAIL // 4 numbers differ, by an absolute total of 0.06
+V8 | KJS # DEFER : LayoutTests/svg/custom/linking-a-03-b-viewBox.svg = FAIL // 2 numbers differ, by an absolute total of 0.04
+V8 | KJS # DEFER : LayoutTests/svg/custom/marker-changes.svg = FAIL // 6 numbers differ, by an absolute total of 5.00
+V8 | KJS # DEFER : LayoutTests/svg/custom/use-css-events.svg = FAIL // 5 numbers differ, by an absolute total of 27.16
+V8 | KJS # DEFER : LayoutTests/svg/custom/use-on-symbol-inside-pattern.svg = FAIL // 11 numbers differ, by an absolute total of 4.69
+V8 | KJS # DEFER : LayoutTests/svg/hixie/perf/001.xml = FAIL // 274 numbers differ, by an absolute total of 157.52
+V8 | KJS # DEFER : LayoutTests/svg/hixie/perf/002.xml = FAIL // 274 numbers differ, by an absolute total of 157.52
+V8 | KJS # DEFER : LayoutTests/svg/hixie/perf/007.xml = FAIL // 745 numbers differ, by an absolute total of 37.97
+V8 | KJS # DEFER : LayoutTests/svg/hixie/shapes/path/001.xml = FAIL // 6 numbers differ, by an absolute total of 100.56
+V8 | KJS # DEFER : LayoutTests/svg/hixie/text/003.html = FAIL // 1 numbers differ, by an absolute total of 1.00
+V8 | KJS # DEFER : LayoutTests/svg/hixie/text/003a.xml = FAIL // 1 numbers differ, by an absolute total of 1.00
+V8 | KJS # DEFER : LayoutTests/svg/hixie/viewbox/preserveAspectRatio/001.xml = FAIL // 2 numbers differ, by an absolute total of 18.00
+V8 | KJS # DEFER : LayoutTests/svg/hixie/viewbox/preserveAspectRatio/002.xml = FAIL // 3 numbers differ, by an absolute total of 3.00
+
+// This is an interesting one.
+// The test has an error which causes it to output a message to the console.
+// Apple's expected results include this error. Actually, Apple's expected
+// results include the error twice, because (apparently unique among console
+// debugging messages) it's generated during rendering. The problem is that
+// we end up invoking the renderer twice when we're doing pixel tests, once
+// otherwise, so we get different results depending on whether pixel tests are
+// enabled. (Neither matches Apple's exactly... when we have pixel tests on,
+// the duplicate error message ends up at the end of the file, while Apple's
+// results have them both at the top.) But this test doesn't represent a real
+// failure in any way and nothing needs to be done to fix it. I'm leaving it
+// in tests_fixable in case we change the test shell's webview delegate to
+// ignore console messages while doing a pixel dump
+V8 | KJS # DEFER : LayoutTests/svg/custom/clip-path-referencing-use2.svg = FAIL
+
+// Bug 1107191. These flakily fail image diffs. Punting on SVG for now.
+// Note that the "expected" images checked in are not necessarily correct.
+V8 # DEFER : LayoutTests/svg/W3C-SVG-1.1/text-text-03-b.svg = PASS | FAIL
+V8 # DEFER : LayoutTests/svg/batik/text/textDecoration2.svg = PASS | FAIL
+V8 # DEFER : LayoutTests/svg/batik/text/textFeatures.svg = PASS | FAIL
+V8 # DEFER : LayoutTests/svg/batik/text/textProperties.svg = PASS | FAIL
+V8 # DEFER : LayoutTests/svg/batik/text/textStyles.svg = PASS | FAIL
+V8 # DEFER : LayoutTests/svg/text/text-text-03-b.svg = PASS | FAIL
+// These consistently fail with image diffs.
+V8 # DEFER : LayoutTests/svg/text/text-deco-01-b.svg = FAIL
+V8 # DEFER : LayoutTests/svg/W3C-SVG-1.1/text-deco-01-b.svg = FAIL
+
+//
+// -----------------------------------------------------------------
+// End of SVG tests
+// -----------------------------------------------------------------
+
+// Bug: 1026885
+// Following tests are failing because Chrome does not allow file url
+// to access non-file urls.
+V8 | KJS # DEFER : LayoutTests/editing/selection/4960137.html = FAIL
+V8 | KJS # DEFER : LayoutTests/editing/selection/cleared-by-relayout.html = FAIL
+V8 | KJS # DEFER : LayoutTests/editing/selection/inactive-selection.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/dom/Element/offsetLeft-offsetTop-body-quirk.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/dom/HTMLObjectElement/object-as-frame.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/dom/clientWidthAfterDocumentIsRemoved.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/dom/wrapper-classes.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/frames/frame-src-attribute.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/leaks/002.html = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/dom/gc-7.html = TIMEOUT
+V8 | KJS # DEFER : LayoutTests/fast/frames/frame-set-same-location.html = TIMEOUT
+V8 | KJS # DEFER : LayoutTests/fast/frames/frame-set-same-src.html = TIMEOUT
+V8 | KJS # DEFER : LayoutTests/fast/frames/hover-timer-crash.html = TIMEOUT
+
+// Bug: 1045048
+// We haven't implemented GCController in test shell
+// Not critical for Beta. We have window.gc() for other tests.
+V8 | KJS # DEFER : LayoutTests/fast/js/garbage-collect-after-string-appends.html = FAIL
+
+// Bug: 1115062
+// These fail the pixel tests in debug mode because they have
+// unpainted space (filled red in Debug but not in Release).
+// These have been filed upstream, and should be deferred from Beta
+// https://bugs.webkit.org/show_bug.cgi?id=8423
+V8 # DEFER : LayoutTests/tables/mozilla_expected_failures/bugs/bug178855.xml = PASS | FAIL
+V8 # DEFER : LayoutTests/fast/flexbox/flex-hang.html = PASS | FAIL
+
+// We expect this to fail because we can't force a GC on KJS.
+// Not sure why it crashes.
+// Once it stops crashing, move back to ignore list.
+KJS # chrome/plugins/refcount-leaks.html = FAIL | CRASH
+
+// Bug: 1112288
+// This test fails in KJS release build.
+// Since this failure is KJS only, we don't care for Beta.
+KJS # DEFER : LayoutTests/fast/js/kde/Number.html = FAIL
+
+// Bug: 1010703
+// Fails only for KJS, so we don't care for Beta.
+KJS # DEFER : chrome/fast/events/nested-window-event.html = FAIL
+
+// Fails only for KJS, so we don't care for Beta.
+KJS # DEFER : chrome/fast/dom/xss-DENIED-javascript-variations.html = FAIL
+
+// Bug: 1093606
+// Crashes both Chrome and Safari. We don't care about KJS for beta.
+KJS # DEFER : chrome/plugins/nested-plugin-objects.html = PASS | CRASH
+
+// Bug: 1155685
+// Flaky, but only on KJS. We don't care about KJS for beta.
+KJS # DEFER : pending/fast/dom/DOMImplementation/singleton-modifications.html = FAIL | PASS
+
+// Bug: 1166260
+V8 # DEFER : LayoutTests/fast/canvas/gradient-empty-path.html = FAIL
+
+// Bug: 1166644
+// Fails on webkit windows as well.
+V8 | KJS # DEFER : LayoutTests/fast/events/attempt-scroll-with-no-scrollbars.html = FAIL
+
+// Bug: 1170198
+// Intentionally failing to avoid XML External Entity exploit
+// until https://bugs.webkit.org/show_bug.cgi?id=19199 is fixed.
+V8 | KJS # DEFER : LayoutTests/fast/parser/external-entities-in-xslt.xml = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/xsl/dtd-in-source-document.xml = FAIL
+V8 | KJS # DEFER : LayoutTests/fast/xsl/xslt-second-level-import.xml = FAIL
+
+// Bug 1226853: Fails on v8-latest after const changes (r123300). Test
+// has been rebaselined (don't declare const x twice).
+V8 # DEFER : LayoutTests/fast/js/const.html = FAIL
+
+// Bug 1237779
+// gc-2.html tests that a DOM tree out of document should be kept alive if
+// one of nodes is reachable from JS side. V8 binding fails because it does
+// not trace DOM objects not in a document.
+// Also the way to trigger GC is not reliable, that's why sometimes it is
+// passing and sometimes not.
+V8 # DEFER : LayoutTests/fast/dom/gc-2.html = FAIL | PASS
diff --git a/webkit/tools/layout_tests/test_lists/tests_ignored.txt b/webkit/tools/layout_tests/test_lists/tests_ignored.txt
new file mode 100644
index 0000000..dc5de8e
--- /dev/null
+++ b/webkit/tools/layout_tests/test_lists/tests_ignored.txt
@@ -0,0 +1,177 @@
+// These tests will be run (unless skipped), but do not expect ever to pass
+// them. They use platform-specific conventions, or features we have decided
+// never to support.
+
+// -----------------------------------------------------------------
+// SKIPPED TESTS
+// -----------------------------------------------------------------
+
+// XHTML tests. See bug 793944. These tests seem like they work, but
+// only because the expected output expects to see JS errors. There is
+// no point in running these tests, because they are giving us a false
+// sense of testing that isn't really happening. Furthermore, since they
+// appear to pass if we do try to run them, we can't even list them as
+// permanently expected to fail.
+V8 | KJS # SKIP : LayoutTests/fast/dom/xmlhttprequest-get.xhtml = PASS
+V8 | KJS # SKIP : LayoutTests/fast/xpath/nsresolver-bad-object.xhtml = PASS
+V8 | KJS # SKIP : LayoutTests/fast/xpath/nsresolver-exception.xhtml = PASS
+V8 | KJS # SKIP : LayoutTests/fast/xpath/nsresolver-function.xhtml = PASS
+V8 | KJS # SKIP : LayoutTests/fast/xpath/nsresolver-object.xhtml = PASS
+V8 | KJS # SKIP : LayoutTests/dom/xhtml = PASS
+
+// Fails due to different window.close() rules. See bug 753420. We need
+// to decide whether we ever expect to pass this. Now also timing out.
+V8 | KJS # SKIP : LayoutTests/fast/dom/open-and-close-by-DOM.html = FAIL
+
+// Fails because we use MIME names for charset while webkit uses IANA names.
+// Instead of this, we added the corresponding test in chrome with the
+// MIME name (EUC-JP) in the expected result.
+V8 | KJS # SKIP : LayoutTests/fast/encoding/hanarei-blog32-fc2-com.html = FAIL
+
+// Skip because of WebKit bug 18512. These bugs "poison" future tests, causing
+// all SVG objects with fill="red" to be rendered in green.
+V8 | KJS # SKIP : LayoutTests/svg/custom/fill-SVGPaint-interface.svg = PASS
+V8 | KJS # SKIP : LayoutTests/svg/custom/getPresentationAttribute.svg = PASS
+
+// -----------------------------------------------------------------
+// FAILING TESTS
+// -----------------------------------------------------------------
+
+// Bug: 1137420
+// We don't intend to pass all of these cases, so this is an expected fail.
+// Window resizing is not implemented in chrome.
+V8 | KJS # LayoutTests/fast/dom/Window/window-resize.html = FAIL
+
+// Chrome uses different keyboard accelerators from those used by Safari, so
+// these tests will always fail.
+V8 | KJS # LayoutTests/editing/pasteboard/emacs-cntl-y-001.html = FAIL
+V8 | KJS # LayoutTests/editing/pasteboard/emacs-ctrl-a-k-y.html = FAIL
+V8 | KJS # LayoutTests/editing/pasteboard/emacs-ctrl-k-y-001.html = FAIL
+V8 | KJS # LayoutTests/editing/input/emacs-ctrl-o.html = FAIL
+
+// These tests check for very kjs-specific garbage collector behavior. Gc-8
+// tests behavior that makes no sense for us to implement. Gc-10 makes sense
+// but would have to be implemented much differently to work in v8.
+V8 | KJS # LayoutTests/fast/dom/gc-8.html = FAIL
+V8 | KJS # LayoutTests/fast/dom/gc-10.html = FAIL
+
+// This fails because we're missing various useless apple-specific
+// properties on the window object.
+// This test also timeouts in Debug mode. See bug 1058654.
+V8 | KJS # LayoutTests/fast/dom/Window/window-properties.html = FAIL | TIMEOUT
+
+// Safari specific test to ensure that JavaScript errors aren't logged when in
+// private browsing mode.
+V8 | KJS # LayoutTests/http/tests/security/cross-frame-access-private-browsing.html = FAIL
+
+// Chrome uses different keyboard accelerators from those used by Safari, so
+// these tests will always fail.
+// TODO(ericroman): can the following 2 tests be removed from this list, since they pass?
+V8 | KJS # LayoutTests/fast/events/keydown-1.html = FAIL
+V8 | KJS # LayoutTests/fast/events/option-tab.html = FAIL
+
+// Chrome does not support WebArchives (just like Safari for Windows).
+// See bug 761653.
+V8 | KJS # LayoutTests/webarchive = FAIL
+V8 | KJS # LayoutTests/svg/webarchive = FAIL
+V8 | KJS # LayoutTests/svg/custom/image-with-prefix-in-webarchive.svg = FAIL
+
+// Bug 932737
+V8 | KJS # LayoutTests/webarchive/loading/test-loading-archive.html = TIMEOUT
+
+// Mac-specific stuff
+// Don't run the platform/mac* tests
+V8 | KJS # LayoutTests/platform = FAIL | PASS
+
+// Ignored because we do not have OBJC bindings
+V8 | KJS # LayoutTests/editing/pasteboard/paste-RTFD.html = FAIL
+V8 | KJS # LayoutTests/editing/pasteboard/paste-TIFF.html = FAIL
+V8 | KJS # LayoutTests/plugins/jsobjc-dom-wrappers.html = FAIL
+V8 | KJS # LayoutTests/plugins/jsobjc-simple.html = FAIL
+V8 | KJS # LayoutTests/plugins/root-object-premature-delete-crash.html = FAIL
+V8 | KJS # LayoutTests/plugins/throw-on-dealloc.html = FAIL
+V8 | KJS # LayoutTests/plugins/undefined-property-crash.html = FAIL
+
+// Uses __apple_runtime_object
+V8 | KJS # LayoutTests/plugins/call-as-function-test.html = FAIL
+
+// Ignore test because it tries to load .pdf files in <img> tags.
+V8 | KJS # LayoutTests/fast/images/pdf-as-image-landscape.html = FAIL
+V8 | KJS # LayoutTests/fast/images/pdf-as-image.html = FAIL
+V8 | KJS # LayoutTests/fast/replaced/pdf-as-image.html = FAIL
+
+// Uses Option-tab key to circle through form elements. Will not work on
+// Windows.
+V8 | KJS # LayoutTests/fast/events/frame-tab-focus.html = FAIL
+
+// Bug 853268: Chrome doesn't call the willCacheResponse callback (a method
+// of ResourceHandleClient). That function is Mac-specific.
+V8 | KJS # LayoutTests/http/tests/misc/willCacheResponse-delegate-callback.html = FAIL
+
+// Checks for very kjs-specific garbage collector
+// behavior. Gc-9 is completely braindamaged; it tests that certain
+// properties are reset by the garbage collector. It looks to pass recently.
+V8 # LayoutTests/fast/dom/gc-9.html = PASS | FAIL
+
+// This test checks that ((new Error()).message is undefined, which is
+// a direct contradiction of the javascript spec 15.11.4.3 which
+// says that it must be a string.
+V8 # LayoutTests/fast/js/kde/evil-n.html = FAIL
+
+// This test is broken. The regular expression used contains an error
+// which kjs swallows and returns false, which is the expected result,
+// but for which we issue a syntax error.
+V8 # LayoutTests/fast/js/code-serialize-paren.html = FAIL
+
+// These tests check for a kjs-specific extension, that source file
+// name and line numbers are available as properties on exception
+// objects. We handle error positions differently.
+V8 # LayoutTests/fast/js/exception-linenums-in-html-1.html = FAIL
+V8 # LayoutTests/fast/js/exception-linenums-in-html-2.html = FAIL
+V8 # LayoutTests/fast/js/exception-linenums.html = FAIL
+
+// These tests rely on specific details of decompilation of
+// functions. V8 always returns the source code as written; there's
+// no decompilation or pretty printing involved except for
+// certain "native" functions where the V8 output does not include
+// newline characters. This is working as intended and we don't care
+// if the tests pass or fail.
+V8 # LayoutTests/fast/js/function-names.html = FAIL | PASS
+
+// WebKit has moved/changed this test upstream
+// https://bugs.webkit.org/show_bug.cgi?id=18681
+// We will pass the new one after we merge
+KJS | V8 # LayoutTests/http/tests/incremental/slow-utf8-css.pl = FAIL
+
+// -----------------------------------------------------------------
+// CHROME REWRITTEN TESTS
+// -----------------------------------------------------------------
+
+// These tests have been rewritten, with the original being ignored,
+// because they were written in ways which are not cross-browser.
+// (e.g. they expect implementation-dependent strings in output)
+V8 # LayoutTests/fast/js/date-proto-generic-invocation.html = FAIL
+V8 # LayoutTests/fast/js/kde/function.html = FAIL
+V8 # LayoutTests/fast/js/kde/inbuilt_function_tostring.html = FAIL
+
+// This test has been rewritten, with the original being ignored,
+// because it depends on a specific enumeration order of properties
+// on dom objects.
+//
+// The rewritten test chrome/fast/dom/domListEnumeration.html tests
+// the exact same thing, but sorts the elements explicitly before
+// comparing.
+V8 # LayoutTests/fast/dom/domListEnumeration.html = FAIL
+
+// Bug 849085: we're taking a different approach on this test than
+// Webkit does.
+KJS | V8 # SKIP : LayoutTests/plugins/get-url-with-blank-target.html = FAIL
+
+// This test doesn't work on the bbot. Works locally.
+KJS | V8 # SKIP : chrome/http/tests/plugins/get-file-url.html = FAIL | PASS | TIMEOUT
+
+
+// These tests tests V8 bindings only, KJS needs to re-baseline the output.
+// See Bug 1205552
+KJS # SKIP : chrome/fast/dom/set-document-body-no-crash.html = FAIL
+KJS # SKIP : chrome/fast/dom/set-table-head-no-crash.html = FAIL
diff --git a/webkit/tools/layout_tests/test_types/__init__.py b/webkit/tools/layout_tests/test_types/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/webkit/tools/layout_tests/test_types/__init__.py
diff --git a/webkit/tools/layout_tests/test_types/image_diff.py b/webkit/tools/layout_tests/test_types/image_diff.py
new file mode 100644
index 0000000..296a1d2
--- /dev/null
+++ b/webkit/tools/layout_tests/test_types/image_diff.py
@@ -0,0 +1,133 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Compares the image output of a test to the expected image output.
+
+Compares hashes for the generated and expected images. If the output doesn't
+match, returns FailureImageHashMismatch and outputs both hashes into the layout
+test results directory.
+"""
+
+import errno
+import os
+import shutil
+
+from layout_package import path_utils
+from layout_package import test_failures
+from test_types import test_type_base
+
+class ImageDiff(test_type_base.TestTypeBase):
+ def _CopyOutputPNGs(self, filename, actual_png, expected_png):
+ """Copies result files into the output directory with appropriate names.
+
+ Args:
+ filename: the test filename
+ actual_png: path to the actual result file
+ expected_png: path to the expected result file
+ """
+ self._MakeOutputDirectory(filename)
+ actual_filename = self.OutputFilename(filename, "-actual-win.png")
+ expected_filename = self.OutputFilename(filename, "-expected.png")
+
+ shutil.copyfile(actual_png, actual_filename)
+ try:
+ shutil.copyfile(expected_png, expected_filename)
+ except IOError, e:
+ # A missing expected PNG has already been recorded as an error.
+ if errno.ENOENT != e.errno:
+ raise
+
+ def _SaveBaselineFiles(self, filename, dest_dir, png_path, checksum):
+ """Saves new baselines for the PNG and checksum.
+
+ Args:
+ filename: test filename
+ dest_dir: outer directory into which the results should be saved.
+ png_path: path to the actual PNG result file
+ checksum: value of the actual checksum result
+ """
+ png_file = open(png_path, "rb")
+ png_data = png_file.read()
+ png_file.close()
+ self._SaveBaselineData(filename, dest_dir, png_data, ".png")
+ self._SaveBaselineData(filename, dest_dir, checksum, ".checksum")
+
+ def CompareOutput(self, filename, proc, output, test_args):
+ """Implementation of CompareOutput that checks the output image and
+ checksum against the expected files from the LayoutTest directory.
+ """
+ failures = []
+
+ # If we didn't produce a hash file, this test must be text-only.
+ if test_args.hash is None:
+ return failures
+
+ # If we're generating a new baseline, we pass.
+ if test_args.new_baseline:
+ self._SaveBaselineFiles(filename, test_args.new_baseline,
+ test_args.png_path, test_args.hash)
+ return failures
+
+ # Compare hashes.
+ expected_hash_file = path_utils.ExpectedFilename(filename,
+ '.checksum',
+ self._custom_result_id)
+
+ expected_png_file = path_utils.ExpectedFilename(filename,
+ '.png',
+ self._custom_result_id)
+
+ try:
+ expected_hash = open(expected_hash_file, "r").read()
+ except IOError, e:
+ if errno.ENOENT != e.errno:
+ raise
+ expected_hash = ''
+
+ if test_args.hash != expected_hash:
+ # TODO(pamg): If the hashes don't match, use the image_diff app to
+ # compare the actual images, and report a different error if those do
+ # match.
+ if expected_hash == '':
+ failures.append(test_failures.FailureMissingImageHash(self))
+ else:
+ failures.append(test_failures.FailureImageHashMismatch(self))
+
+ # Also report a missing expected PNG file.
+ if not os.path.isfile(expected_png_file):
+ failures.append(test_failures.FailureMissingImage(self))
+
+ # If anything was wrong, write the output files.
+ if len(failures):
+ self.WriteOutputFiles(filename, '', '.checksum', test_args.hash,
+ expected_hash, diff=False)
+ self._CopyOutputPNGs(filename, test_args.png_path,
+ expected_png_file)
+
+ return failures
diff --git a/webkit/tools/layout_tests/test_types/simplified_text_diff.py b/webkit/tools/layout_tests/test_types/simplified_text_diff.py
new file mode 100644
index 0000000..419a7c3
--- /dev/null
+++ b/webkit/tools/layout_tests/test_types/simplified_text_diff.py
@@ -0,0 +1,141 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Compares the text output to the expected text output while ignoring
+positions and sizes of elements/text.
+
+If the output doesn't match, returns FailureSimplifiedTextMismatch and outputs
+the diff files into the layout test results directory.
+"""
+
+import difflib
+import os.path
+import re
+
+from layout_package import test_failures
+from test_types import text_diff
+
+class SimplifiedTextDiff(text_diff.TestTextDiff):
+ def _SimplifyText(self, text):
+ """Removes position and size information from a render tree dump. This
+ also combines contiguous lines of text together so lines that wrap between
+ different words match. Returns the simplified text."""
+
+ # SVG render paths are a little complicated: we want to strip digits after
+ # a decimal point only for strings that begin with "RenderPath.*data".
+ def simplify_svg_path(match):
+ return match.group(1) + re.sub(r"([0-9]*)\.[0-9]{2}", "\\1", match.group(2))
+
+ # Regular expressions to remove or substitue text.
+ simplifications = (
+ # Ignore TypeError and ReferenceError, V8 has different error text.
+ (re.compile(r"Message\tTypeError:.*"), 'Message\tTypeError:'),
+ (re.compile(r"Message\tReferenceError:.*"), 'Message\tReferenceError:'),
+
+ # Ignore uncaught exceptions because V8s error messages are different.
+ (re.compile(r"CONSOLE MESSAGE: line \d+: .*"), 'CONSOLE MESSAGE: line'),
+
+ # Remove position and size information from text.
+ (re.compile(r"at \(-?[0-9]+(\.[0-9]+)?,-?[0-9]+(\.[0-9]+)?\) *"), ''),
+ (re.compile(r"size -?[0-9]+(\.[0-9]+)?x-?[0-9]+(\.[0-9]+)? *"), ''),
+ (re.compile(r' RTL: "\."'), ': ""'),
+ (re.compile(r" (RTL|LTR)( override)?: "), ': '),
+ (re.compile(r"text run width -?[0-9]+: "), ''),
+ (re.compile(r"\([0-9]+px"), ''),
+ (re.compile(r"scrollHeight -?[0-9]+"), ''),
+ (re.compile(r"scrollWidth -?[0-9]+"), ''),
+ (re.compile(r"scrollX -?[0-9]+"), ''),
+ (re.compile(r"scrollY -?[0-9]+"), ''),
+ (re.compile(r"scrolled to [0-9]+,[0-9]+"), 'scrolled to'),
+ (re.compile(r"caret: position -?[0-9]+"), ''),
+
+ # The file select widget has different text on Mac and Win.
+ (re.compile(r"Choose File"), "Browse..."),
+
+ # Remove trailing spaces at the end of a line of text.
+ (re.compile(r' "\n'), '"\n'),
+ # Remove leading spaces at the beginning of a line of text.
+ (re.compile(r'(\s+") '), '\\1'),
+ # Remove empty lines (this only seems to happen with <textareas>)
+ (re.compile(r'^\s*""\n', re.M), ''),
+ # Merge text lines together. Lines ending in anything other than a
+ # hyphen get a space inserted when joined.
+ (re.compile(r'-"\s+"', re.M), '-'),
+ (re.compile(r'"\s+"', re.M), ' '),
+
+ # Handle RTL "...Browse" text. The space gets inserted when text lines
+ # are merged together in the step above.
+ (re.compile(r"... Browse"), "Browse..."),
+
+ # Some SVG tests inexplicably emit -0.00 rather than 0.00 in the expected results
+ (re.compile(r"-0\.00"), '0.00'),
+
+ # Remove size information from SVG text
+ (re.compile(r"(chunk.*width )([0-9]+\.[0-9]{2})"), '\\1'),
+
+ # Remove decimals from SVG paths
+ (re.compile(r"(RenderPath.*data)(.*)"), simplify_svg_path),
+ )
+
+ for regex, subst in simplifications:
+ text = re.sub(regex, subst, text)
+
+ return text
+
+ def CompareOutput(self, filename, proc, output, unused_test_args):
+ """Implementation of CompareOutput that removes most numbers before
+ computing the diff.
+
+ This test does not save new baseline results.
+
+ """
+ failures = []
+
+ # Normalize text to diff
+ output = self.GetNormalizedOutputText(output)
+ expected = self.GetNormalizedExpectedText(filename)
+
+ # Don't bother with the simplified text diff if we match before simplifying
+ # the text.
+ if output == expected:
+ return failures
+
+ # Make the simplified text.
+ output = self._SimplifyText(output)
+ expected = self._SimplifyText(expected)
+
+ if output != expected:
+ # Text doesn't match, write output files.
+ self.WriteOutputFiles(filename, "-simp", ".txt", output, expected)
+
+ # Add failure to return list, unless it's a new test.
+ if expected != '':
+ failures.append(test_failures.FailureSimplifiedTextMismatch(self))
+
+ return failures
diff --git a/webkit/tools/layout_tests/test_types/test_type_base.py b/webkit/tools/layout_tests/test_types/test_type_base.py
new file mode 100644
index 0000000..8afc316
--- /dev/null
+++ b/webkit/tools/layout_tests/test_types/test_type_base.py
@@ -0,0 +1,189 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Defines the interface TestTypeBase which other test types inherit from.
+
+Also defines the TestArguments "struct" to pass them additional arguments.
+"""
+
+import difflib
+import os.path
+
+
+import google.path_utils
+
+from layout_package import path_utils
+from layout_package import platform_utils
+
+class TestArguments(object):
+ """Struct-like wrapper for additional arguments needed by specific tests."""
+ # Outer directory in which to place new baseline results.
+ new_baseline = None
+
+ # Whether to save new text baseline files (otherwise only save image
+ # results as a new baseline).
+ text_baseline = False
+
+ # Path to the actual PNG file generated by pixel tests
+ png_path = None
+
+ # Value of checksum generated by pixel tests.
+ hash = None
+
+
+class TestTypeBase(object):
+ # Filename pieces when writing failures to the test results directory.
+ FILENAME_SUFFIX_ACTUAL = "-actual-win"
+ FILENAME_SUFFIX_EXPECTED = "-expected"
+ FILENAME_SUFFIX_DIFF = "-diff-win"
+
+ def __init__(self, custom_result_id, root_output_dir):
+ """Initialize a TestTypeBase object.
+
+ Args:
+ custom_result_id: the string (generally 'kjs' or 'v8') identifying the
+ custom expected results to be used
+ root_output_dir: The unix style path to the output dir.
+ """
+ self._root_output_dir = root_output_dir
+ self._custom_result_id = custom_result_id
+
+ def _MakeOutputDirectory(self, filename):
+ """Creates the output directory (if needed) for a given test filename."""
+ output_filename = os.path.join(self._root_output_dir,
+ path_utils.RelativeTestFilename(filename))
+ google.path_utils.MaybeMakeDirectory(os.path.split(output_filename)[0])
+
+ def _SaveBaselineData(self, filename, dest_dir, data, modifier):
+ """Saves a new baseline file.
+
+ The file will be named simply "<test>-expected<modifier>", suitable for
+ use as the expected results in a later run.
+
+ Args:
+ filename: the test filename
+ dest_dir: the outer directory into which the results should be saved.
+ The subdirectory corresponding to this test will be created if
+ necessary.
+ data: result to be saved as the new baseline
+ modifier: type of the result file, e.g. ".txt" or ".png"
+ """
+ output_filename = os.path.join(dest_dir,
+ path_utils.RelativeTestFilename(filename))
+ output_filename = (os.path.splitext(output_filename)[0] +
+ self.FILENAME_SUFFIX_EXPECTED + modifier)
+ google.path_utils.MaybeMakeDirectory(os.path.split(output_filename)[0])
+ open(output_filename, "wb").write(data)
+
+ def OutputFilename(self, filename, modifier):
+ """Returns a filename inside the output dir that contains modifier.
+
+ For example, if filename is c:/.../fast/dom/foo.html and modifier is
+ "-expected.txt", the return value is
+ c:/cygwin/tmp/layout-test-results/fast/dom/foo-expected.txt
+
+ Args:
+ filename: absolute filename to test file
+ modifier: a string to replace the extension of filename with
+
+ Return:
+ The absolute windows path to the output filename
+ """
+ output_filename = os.path.join(self._root_output_dir,
+ path_utils.RelativeTestFilename(filename))
+ return os.path.splitext(output_filename)[0] + modifier
+
+ def RelativeOutputFilename(self, filename, modifier):
+ """Returns a relative filename inside the output dir that contains
+ modifier.
+
+ For example, if filename is fast\dom\foo.html and modifier is
+ "-expected.txt", the return value is fast\dom\foo-expected.txt
+
+ Args:
+ filename: relative filename to test file
+ modifier: a string to replace the extension of filename with
+
+ Return:
+ The relative windows path to the output filename
+ """
+ return os.path.splitext(filename)[0] + modifier
+
+ def CompareOutput(self, filename, proc, output, test_args):
+ """Method that compares the output from the test with the expected value.
+
+ This is an abstract method to be implemented by all sub classes.
+
+ Args:
+ filename: absolute filename to test file
+ proc: a reference to the test_shell process
+ output: a string containing the output of the test
+ test_args: a TestArguments object holding optional additional arguments
+
+ Return:
+ a list of TestFailure objects, empty if the test passes
+ """
+ raise NotImplemented
+
+ def WriteOutputFiles(self, filename, test_type, file_type, output, expected,
+ diff=True):
+ """Writes the test output, the expected output and optionally the diff
+ between the two to files in the results directory.
+
+ The full output filename of the actual, for example, will be
+ <filename><test_type>-actual-win<file_type>
+ For instance,
+ my_test-simp-actual-win.txt
+
+ Args:
+ filename: The test filename
+ prefix: A string appended to the test filename, e.g. "-simp". May be "".
+ suffix: A string describing the test output file type, e.g. ".txt"
+ output: A string containing the test output
+ expected: A string containing the expected test output
+ diff: if True, write a file containing the diffs too. This should be
+ False for results that are not text.
+ """
+ self._MakeOutputDirectory(filename)
+ actual_filename = self.OutputFilename(filename,
+ test_type + self.FILENAME_SUFFIX_ACTUAL + file_type)
+ expected_win_filename = self.OutputFilename(filename,
+ test_type + self.FILENAME_SUFFIX_EXPECTED + file_type)
+ open(actual_filename, "wb").write(output)
+ open(expected_win_filename, "wb").write(expected)
+
+ if diff:
+ diff = difflib.unified_diff(expected.splitlines(True),
+ output.splitlines(True),
+ expected_win_filename,
+ actual_filename)
+
+ diff_filename = self.OutputFilename(filename,
+ test_type + self.FILENAME_SUFFIX_DIFF + file_type)
+ open(diff_filename, "wb").write(''.join(diff))
diff --git a/webkit/tools/layout_tests/test_types/text_diff.py b/webkit/tools/layout_tests/test_types/text_diff.py
new file mode 100644
index 0000000..b58fb6a
--- /dev/null
+++ b/webkit/tools/layout_tests/test_types/text_diff.py
@@ -0,0 +1,95 @@
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Compares the text output of a test to the expected text output.
+
+If the output doesn't match, returns FailureTextMismatch and outputs the diff
+files into the layout test results directory.
+"""
+
+import errno
+import os.path
+
+from layout_package import path_utils
+from layout_package import platform_utils
+from layout_package import test_failures
+from test_types import test_type_base
+
+class TestTextDiff(test_type_base.TestTypeBase):
+ def GetNormalizedOutputText(self, output):
+ # Some tests produce "\r\n" explicitly. Our system (Python/Cygwin)
+ # helpfully changes the "\n" to "\r\n", resulting in "\r\r\n".
+ norm = output.replace("\r\r\n", "\r\n").strip("\r\n").replace("\r\n", "\n")
+ return norm + "\n"
+
+ def GetNormalizedExpectedText(self, filename):
+ """Given the filename of the test, read the expected output from a file
+ and normalize the text. Returns a string with the expected text, or ''
+ if the expected output file was not found."""
+ # Read the platform-specific expected text, or the Mac default if no
+ # platform result exists.
+ expected_filename = path_utils.ExpectedFilename(filename, '.txt',
+ self._custom_result_id)
+ try:
+ expected = open(expected_filename).read()
+ except IOError, e:
+ if errno.ENOENT != e.errno:
+ raise
+ expected = ''
+ return expected
+
+ # Normalize line endings
+ return expected.strip("\r\n") + "\n"
+
+ def CompareOutput(self, filename, proc, output, test_args):
+ """Implementation of CompareOutput that checks the output text against the
+ expected text from the LayoutTest directory."""
+ failures = []
+
+ # If we're generating a new baseline, we pass.
+ if test_args.text_baseline:
+ self._SaveBaselineData(filename, test_args.new_baseline,
+ output, ".txt")
+ return failures
+
+ # Normalize text to diff
+ output = self.GetNormalizedOutputText(output)
+ expected = self.GetNormalizedExpectedText(filename)
+
+ # Write output files for new tests, too.
+ if output != expected:
+ # Text doesn't match, write output files.
+ self.WriteOutputFiles(filename, "", ".txt", output, expected)
+
+ if expected == '':
+ failures.append(test_failures.FailureMissingResult(self))
+ else:
+ failures.append(test_failures.FailureTextMismatch(self))
+
+ return failures
diff --git a/webkit/tools/layout_tests/testdata/README b/webkit/tools/layout_tests/testdata/README
new file mode 100644
index 0000000..563e442
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/README
@@ -0,0 +1,2 @@
+This directory contains fake data used by the unittests for
+run_webkit_tests.py.
diff --git a/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-actual-win.txt b/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-actual-win.txt
new file mode 100644
index 0000000..2606bcd
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-actual-win.txt
@@ -0,0 +1,369 @@
+layer at (0,0) size 783x732
+ RenderView at (0,0) size 783x600
+layer at (0,0) size 783x732
+ RenderBlock {HTML} at (0,0) size 783x732
+ RenderBody {BODY} at (8,8) size 767x716
+ RenderBlock {H1} at (0,0) size 767x37
+ RenderText {#text} at (0,0) size 420x36
+ text run at (0,0) width 420: "Form Element Geometry Tests"
+ RenderBlock {P} at (0,58) size 767x20
+ RenderText {#text} at (0,0) size 514x19
+ text run at (0,0) width 514: "These tests help us tune the widget classes in KWQ to have all the right fudge factors."
+ RenderBlock {H2} at (0,97) size 767x27
+ RenderText {#text} at (0,0) size 165x26
+ text run at (0,0) width 165: "Bounding Boxes"
+ RenderTable {TABLE} at (0,143) size 214x47
+ RenderTableSection {TBODY} at (0,0) size 214x47
+ RenderTableRow {TR} at (0,2) size 214x43
+ RenderTableCell {TD} at (2,2) size 84x43 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 82x41 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 78x27
+ RenderButton {INPUT} at (2,2) size 78x37 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 62x28
+ RenderText at (0,0) size 62x27
+ text run at (0,0) width 62: "button"
+ RenderTableCell {TD} at (88,4) size 82x38 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 80x36 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 76x27
+ RenderMenuList {SELECT} at (2,2) size 76x32 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 53x28
+ RenderText at (0,0) size 53x27
+ text run at (0,0) width 53: "menu"
+ RenderBlock (anonymous) at (1,37) size 80x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTableCell {TD} at (172,14) size 19x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 13x13
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderBlock (anonymous) at (1,18) size 17x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTableCell {TD} at (193,14) size 19x19 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 13x13
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderBlock (anonymous) at (1,18) size 17x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTable {TABLE} at (0,190) size 169x39
+ RenderTableSection {TBODY} at (0,0) size 169x39
+ RenderTableRow {TR} at (0,2) size 169x35
+ RenderTableCell {TD} at (2,2) size 60x35 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 58x33 [border: (2px solid #0000FF)]
+ RenderButton {INPUT} at (2,2) size 54x29 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 38x20
+ RenderText at (0,0) size 38x19
+ text run at (0,0) width 38: "button"
+ RenderTableCell {TD} at (64,4) size 61x30 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 59x28 [border: (2px solid #0000FF)]
+ RenderMenuList {SELECT} at (2,2) size 55x24 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 32x20
+ RenderText at (0,0) size 32x19
+ text run at (0,0) width 32: "menu"
+ RenderTableCell {TD} at (127,10) size 19x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderTableCell {TD} at (148,10) size 19x19 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderTable {TABLE} at (0,229) size 147x31
+ RenderTableSection {TBODY} at (0,0) size 147x31
+ RenderTableRow {TR} at (0,2) size 147x27
+ RenderTableCell {TD} at (2,2) size 48x27 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 46x25 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 42x12
+ RenderButton {INPUT} at (2,2) size 42x21 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 26x12
+ RenderText at (0,0) size 26x12
+ text run at (0,0) width 26: "button"
+ RenderTableCell {TD} at (52,4) size 51x22 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 49x20 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 45x12
+ RenderMenuList {SELECT} at (2,2) size 45x16 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 22x12
+ RenderText at (0,0) size 22x12
+ text run at (0,0) width 22: "menu"
+ RenderTableCell {TD} at (105,6) size 19x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 13x10
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderTableCell {TD} at (126,6) size 19x19 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 17x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 13x10
+ RenderBlock {INPUT} at (2,2) size 13x13
+ RenderTable {TABLE} at (0,260) size 622x91
+ RenderTableSection {TBODY} at (0,0) size 622x91
+ RenderTableRow {TR} at (0,2) size 622x87
+ RenderTableCell {TD} at (2,2) size 94x32 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 92x30 [border: (2px solid #0000FF)]
+ RenderTextControl {INPUT} at (2,2) size 88x26 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderTableCell {TD} at (98,2) size 45x87 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 43x85 [border: (2px solid #0000FF)]
+ RenderListBox {SELECT} at (2,2) size 39x81 [bgcolor=#FFFFFF] [border: (1px inset #808080)]
+ RenderTableCell {TD} at (145,2) size 278x35 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 276x33 [border: (2px solid #0000FF)]
+ RenderFileUploadControl {INPUT} at (2,2) size 272x29
+ RenderButton {INPUT} at (0,0) size 75x29 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (425,2) size 195x52 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 193x50 [border: (2px solid #0000FF)]
+ RenderTextControl {TEXTAREA} at (4,4) size 185x42 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderBlock {H2} at (0,370) size 767x27
+ RenderText {#text} at (0,0) size 199x26
+ text run at (0,0) width 199: "Baseline Alignment"
+ RenderBlock {DIV} at (0,416) size 767x41
+ RenderInline {FONT} at (0,0) size 269x27
+ RenderText {#text} at (0,6) size 43x27
+ text run at (0,6) width 43: "text "
+ RenderButton {INPUT} at (45,2) size 78x37 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 62x28
+ RenderText at (0,0) size 62x27
+ text run at (0,0) width 62: "button"
+ RenderText {#text} at (125,6) size 6x27
+ text run at (125,6) width 6: " "
+ RenderMenuList {SELECT} at (133,4) size 76x32 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 53x28
+ RenderText at (0,0) size 53x27
+ text run at (0,0) width 53: "menu"
+ RenderText {#text} at (211,6) size 6x27
+ text run at (211,6) width 6: " "
+ RenderBlock {INPUT} at (222,14) size 13x13
+ RenderText {#text} at (240,6) size 6x27
+ text run at (240,6) width 6: " "
+ RenderBlock {INPUT} at (251,14) size 13x13
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,457) size 767x33
+ RenderText {#text} at (0,6) size 26x19
+ text run at (0,6) width 26: "text "
+ RenderButton {INPUT} at (28,2) size 54x29 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 38x20
+ RenderText at (0,0) size 38x19
+ text run at (0,0) width 38: "button"
+ RenderText {#text} at (84,6) size 4x19
+ text run at (84,6) width 4: " "
+ RenderMenuList {SELECT} at (90,4) size 55x24 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 32x20
+ RenderText at (0,0) size 32x19
+ text run at (0,0) width 32: "menu"
+ RenderText {#text} at (147,6) size 4x19
+ text run at (147,6) width 4: " "
+ RenderBlock {INPUT} at (155,8) size 13x13
+ RenderText {#text} at (172,6) size 4x19
+ text run at (172,6) width 4: " "
+ RenderBlock {INPUT} at (180,8) size 13x13
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,490) size 767x23
+ RenderInline {FONT} at (0,0) size 148x12
+ RenderText {#text} at (0,6) size 18x12
+ text run at (0,6) width 18: "text "
+ RenderButton {INPUT} at (18,2) size 42x21 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 26x12
+ RenderText at (0,0) size 26x12
+ text run at (0,0) width 26: "button"
+ RenderText {#text} at (60,6) size 3x12
+ text run at (60,6) width 3: " "
+ RenderMenuList {SELECT} at (63,4) size 45x16 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 22x12
+ RenderText at (0,0) size 22x12
+ text run at (0,0) width 22: "menu"
+ RenderText {#text} at (108,6) size 3x12
+ text run at (108,6) width 3: " "
+ RenderBlock {INPUT} at (113,3) size 13x13
+ RenderText {#text} at (128,6) size 3x12
+ text run at (128,6) width 3: " "
+ RenderBlock {INPUT} at (133,3) size 13x13
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,513) size 767x58
+ RenderText {#text} at (0,31) size 26x19
+ text run at (0,31) width 26: "text "
+ RenderTextControl {INPUT} at (28,28) size 88x26 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderText {#text} at (118,31) size 4x19
+ text run at (118,31) width 4: " "
+ RenderFileUploadControl {INPUT} at (124,27) size 272x29
+ RenderButton {INPUT} at (0,0) size 75x29 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,4) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderText {#text} at (398,31) size 4x19
+ text run at (398,31) width 4: " "
+ RenderTextControl {TEXTAREA} at (404,2) size 185x42 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {H2} at (0,590) size 767x27
+ RenderText {#text} at (0,0) size 195x26
+ text run at (0,0) width 195: "Pop-up Menu Sizes"
+ RenderBlock {DIV} at (0,636) size 767x36
+ RenderInline {FONT} at (0,0) size 194x27
+ RenderText {#text} at (0,0) size 0x0
+ RenderMenuList {SELECT} at (2,2) size 23x32 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 0x28
+ RenderBR at (0,0) size 0x27 [bgcolor=#FFFFFF]
+ RenderText {#text} at (27,4) size 6x27
+ text run at (27,4) width 6: " "
+ RenderMenuList {SELECT} at (35,2) size 28x32 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 5x28
+ RenderText at (0,0) size 5x27
+ text run at (0,0) width 5: "|"
+ RenderText {#text} at (65,4) size 6x27
+ text run at (65,4) width 6: " "
+ RenderMenuList {SELECT} at (73,2) size 119x32 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 96x28
+ RenderText at (0,0) size 96x27
+ text run at (0,0) width 96: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,672) size 767x28
+ RenderMenuList {SELECT} at (2,2) size 23x24 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 0x20
+ RenderBR at (0,0) size 0x19 [bgcolor=#FFFFFF]
+ RenderText {#text} at (27,4) size 4x19
+ text run at (27,4) width 4: " "
+ RenderMenuList {SELECT} at (33,2) size 26x24 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 3x20
+ RenderText at (0,0) size 3x19
+ text run at (0,0) width 3: "|"
+ RenderText {#text} at (61,4) size 4x19
+ text run at (61,4) width 4: " "
+ RenderMenuList {SELECT} at (67,2) size 79x24 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 56x20
+ RenderText at (0,0) size 56x19
+ text run at (0,0) width 56: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,700) size 767x16
+ RenderInline {FONT} at (0,0) size 118x12
+ RenderText {#text} at (0,0) size 0x0
+ RenderMenuList {SELECT} at (0,0) size 23x16 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 0x12
+ RenderBR at (0,0) size 0x12 [bgcolor=#FFFFFF]
+ RenderText {#text} at (23,2) size 3x12
+ text run at (23,2) width 3: " "
+ RenderMenuList {SELECT} at (26,0) size 26x16 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 3x12
+ RenderText at (0,0) size 3x12
+ text run at (0,0) width 3: "|"
+ RenderText {#text} at (52,2) size 3x12
+ text run at (52,2) width 3: " "
+ RenderMenuList {SELECT} at (55,0) size 63x16 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (3,2) size 40x12
+ RenderText at (0,0) size 40x12
+ text run at (0,0) width 40: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+layer at (16,276) size 82x20
+ RenderBlock {DIV} at (3,3) size 82x20
+ RenderText {#text} at (1,0) size 51x19
+ text run at (1,0) width 51: "text field"
+layer at (439,276) size 183x40
+ RenderBlock {DIV} at (1,1) size 183x40
+ RenderText {#text} at (3,0) size 48x19
+ text run at (3,0) width 48: "textarea"
+layer at (39,552) size 82x20
+ RenderBlock {DIV} at (3,3) size 82x20
+ RenderText {#text} at (1,0) size 51x19
+ text run at (1,0) width 51: "text field"
+layer at (413,524) size 183x40
+ RenderBlock {DIV} at (1,1) size 183x40
+ RenderText {#text} at (3,0) size 48x19
+ text run at (3,0) width 48: "textarea"
+layer at (0,0) size 1220x583
+ RenderView at (0,0) size 800x583
+layer at (0,0) size 1220x583
+ RenderBlock {HTML} at (0,0) size 800x583
+ RenderBody {BODY} at (8,8) size 784x567
+ RenderTable {TABLE} at (0,0) size 1212x131
+ RenderTableSection {TBODY} at (0,0) size 1212x131
+ RenderTableRow {TR} at (0,2) size 1212x22
+ RenderTableCell {TH} at (2,12) size 80x2 [r=0 c=0 rs=1 cs=1]
+ RenderTableCell {TH} at (84,12) size 280x2 [r=0 c=1 rs=1 cs=1]
+ RenderTableCell {TH} at (366,2) size 280x22 [r=0 c=2 rs=1 cs=1]
+ RenderText {#text} at (95,1) size 90x19
+ text run at (95,1) width 90: "text-align:left"
+ RenderTableCell {TH} at (648,2) size 280x22 [r=0 c=3 rs=1 cs=1]
+ RenderText {#text} at (85,1) size 110x19
+ text run at (85,1) width 110: "text-align:center"
+ RenderTableCell {TH} at (930,2) size 280x22 [r=0 c=4 rs=1 cs=1]
+ RenderText {#text} at (90,1) size 99x19
+ text run at (90,1) width 99: "text-align:right"
+ RenderTableRow {TR} at (0,26) size 1212x33
+ RenderTableCell {TH} at (2,41) size 80x2 [r=1 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (84,26) size 280x33 [border: (1px solid #000000)] [r=1 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (366,26) size 280x33 [border: (1px solid #000000)] [r=1 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (648,26) size 280x33 [border: (1px solid #000000)] [r=1 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (930,26) size 280x33 [border: (1px solid #000000)] [r=1 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableRow {TR} at (0,61) size 1212x33
+ RenderTableCell {TH} at (2,66) size 80x22 [r=2 c=0 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 78x19
+ text run at (1,1) width 78: "direction:ltr"
+ RenderTableCell {TD} at (84,61) size 280x33 [border: (1px solid #000000)] [r=2 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (366,61) size 280x33 [border: (1px solid #000000)] [r=2 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (648,61) size 280x33 [border: (1px solid #000000)] [r=2 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableCell {TD} at (930,61) size 280x33 [border: (1px solid #000000)] [r=2 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (0,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 59: "Browse..."
+ RenderTableRow {TR} at (0,96) size 1212x33
+ RenderTableCell {TH} at (2,101) size 80x22 [r=3 c=0 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 78x19
+ text run at (1,1) width 78: "direction:rtl"
+ RenderTableCell {TD} at (84,96) size 280x33 [border: (1px solid #000000)] [r=3 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (201,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 12 RTL: "..."
+ text run at (12,0) width 47: "Browse"
+ RenderTableCell {TD} at (366,96) size 280x33 [border: (1px solid #000000)] [r=3 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (201,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 12 RTL: "..."
+ text run at (12,0) width 47: "Browse"
+ RenderTableCell {TD} at (648,96) size 280x33 [border: (1px solid #000000)] [r=3 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (201,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 12 RTL: "..."
+ text run at (12,0) width 47: "Browse"
+ RenderTableCell {TD} at (930,96) size 280x33 [border: (1px solid #000000)] [r=3 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 272x25
+ RenderButton {INPUT} at (201,0) size 71x25 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (6,2) size 59x20
+ RenderText at (0,0) size 59x19
+ text run at (0,0) width 12 RTL: "..."
+ text run at (12,0) width 47: "Browse"
diff --git a/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-expected.txt b/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-expected.txt
new file mode 100644
index 0000000..e421005
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/form-element-geometry-expected.txt
@@ -0,0 +1,365 @@
+layer at (0,0) size 785x626
+ RenderView at (0,0) size 785x600
+layer at (0,0) size 785x626
+ RenderBlock {HTML} at (0,0) size 785x626
+ RenderBody {BODY} at (8,8) size 769x610
+ RenderBlock {H1} at (0,0) size 769x37
+ RenderText {#text} at (0,0) size 422x37
+ text run at (0,0) width 422: "Form Element Geometry Tests"
+ RenderBlock {P} at (0,58) size 769x18
+ RenderText {#text} at (0,0) size 540x18
+ text run at (0,0) width 540: "These tests help us tune the widget classes in KWQ to have all the right fudge factors."
+ RenderBlock {H2} at (0,95) size 769x28
+ RenderText {#text} at (0,0) size 165x28
+ text run at (0,0) width 165: "Bounding Boxes"
+ RenderTable {TABLE} at (0,142) size 172x28
+ RenderTableSection {TBODY} at (0,0) size 172x28
+ RenderTableRow {TR} at (0,2) size 172x24
+ RenderTableCell {TD} at (2,2) size 58x24 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 56x22 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 52x18
+ RenderButton {INPUT} at (2,2) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderTableCell {TD} at (62,2) size 68x24 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 66x22 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 62x18
+ RenderMenuList {SELECT} at (2,2) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderBlock (anonymous) at (1,23) size 66x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTableCell {TD} at (132,4) size 18x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 12x13
+ RenderBlock {INPUT} at (2,2) size 12x13
+ RenderBlock (anonymous) at (1,18) size 16x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTableCell {TD} at (152,5) size 18x18 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x16 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 12x12
+ RenderBlock {INPUT} at (2,2) size 12x12
+ RenderBlock (anonymous) at (1,17) size 16x0
+ RenderInline {FONT} at (0,0) size 0x0
+ RenderTable {TABLE} at (0,170) size 172x28
+ RenderTableSection {TBODY} at (0,0) size 172x28
+ RenderTableRow {TR} at (0,2) size 172x24
+ RenderTableCell {TD} at (2,2) size 58x24 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 56x22 [border: (2px solid #0000FF)]
+ RenderButton {INPUT} at (2,2) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderTableCell {TD} at (62,2) size 68x24 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 66x22 [border: (2px solid #0000FF)]
+ RenderMenuList {SELECT} at (2,2) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderTableCell {TD} at (132,4) size 18x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x17 [border: (2px solid #0000FF)]
+ RenderBlock {INPUT} at (2,2) size 12x13
+ RenderTableCell {TD} at (152,5) size 18x18 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x16 [border: (2px solid #0000FF)]
+ RenderBlock {INPUT} at (2,2) size 12x12
+ RenderTable {TABLE} at (0,198) size 172x28
+ RenderTableSection {TBODY} at (0,0) size 172x28
+ RenderTableRow {TR} at (0,2) size 172x24
+ RenderTableCell {TD} at (2,2) size 58x24 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 56x22 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 52x13
+ RenderButton {INPUT} at (2,2) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderTableCell {TD} at (62,2) size 68x24 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 66x22 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 62x13
+ RenderMenuList {SELECT} at (2,2) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderTableCell {TD} at (132,4) size 18x19 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x17 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 12x12
+ RenderBlock {INPUT} at (2,2) size 12x13
+ RenderTableCell {TD} at (152,5) size 18x18 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 16x16 [border: (2px solid #0000FF)]
+ RenderInline {FONT} at (0,0) size 12x12
+ RenderBlock {INPUT} at (2,2) size 12x12
+ RenderTable {TABLE} at (0,226) size 550x67
+ RenderTableSection {TBODY} at (0,0) size 550x67
+ RenderTableRow {TR} at (0,2) size 550x63
+ RenderTableCell {TD} at (2,2) size 84x25 [r=0 c=0 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 82x23 [border: (2px solid #0000FF)]
+ RenderTextControl {INPUT} at (2,2) size 78x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderTableCell {TD} at (88,2) size 40x63 [r=0 c=1 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 38x61 [border: (2px solid #0000FF)]
+ RenderListBox {SELECT} at (2,2) size 34x57 [bgcolor=#FFFFFF] [border: (1px inset #808080)]
+ RenderTableCell {TD} at (130,2) size 243x24 [r=0 c=2 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 241x22 [border: (2px solid #0000FF)]
+ RenderFileUploadControl {INPUT} at (2,2) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (375,2) size 173x38 [r=0 c=3 rs=1 cs=1]
+ RenderBlock {DIV} at (1,1) size 171x36 [border: (2px solid #0000FF)]
+ RenderTextControl {TEXTAREA} at (4,4) size 163x28 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderBlock {H2} at (0,312) size 769x28
+ RenderText {#text} at (0,0) size 200x28
+ text run at (0,0) width 200: "Baseline Alignment"
+ RenderBlock {DIV} at (0,359) size 769x29
+ RenderInline {FONT} at (0,0) size 219x28
+ RenderText {#text} at (0,0) size 43x28
+ text run at (0,0) width 43: "text "
+ RenderButton {INPUT} at (45,9) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderText {#text} at (99,0) size 6x28
+ text run at (99,0) width 6: " "
+ RenderMenuList {SELECT} at (107,9) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderText {#text} at (171,0) size 6x28
+ text run at (171,0) width 6: " "
+ RenderBlock {INPUT} at (180,11) size 12x13
+ RenderText {#text} at (195,0) size 6x28
+ text run at (195,0) width 6: " "
+ RenderBlock {INPUT} at (204,12) size 12x12
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,388) size 769x22
+ RenderText {#text} at (0,1) size 27x18
+ text run at (0,1) width 27: "text "
+ RenderButton {INPUT} at (29,2) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderText {#text} at (83,1) size 4x18
+ text run at (83,1) width 4: " "
+ RenderMenuList {SELECT} at (89,2) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderText {#text} at (153,1) size 4x18
+ text run at (153,1) width 4: " "
+ RenderBlock {INPUT} at (160,4) size 12x13
+ RenderText {#text} at (175,1) size 4x18
+ text run at (175,1) width 4: " "
+ RenderBlock {INPUT} at (182,5) size 12x12
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,410) size 769x22
+ RenderInline {FONT} at (0,0) size 185x13
+ RenderText {#text} at (0,5) size 18x13
+ text run at (0,5) width 18: "text "
+ RenderButton {INPUT} at (20,2) size 52x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 36x13
+ RenderText at (0,0) size 36x13
+ text run at (0,0) width 36: "button"
+ RenderText {#text} at (74,5) size 3x13
+ text run at (74,5) width 3: " "
+ RenderMenuList {SELECT} at (79,2) size 62x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 31x13
+ RenderText at (0,0) size 31x13
+ text run at (0,0) width 31: "menu"
+ RenderText {#text} at (143,5) size 3x13
+ text run at (143,5) width 3: " "
+ RenderBlock {INPUT} at (149,4) size 12x13
+ RenderText {#text} at (164,5) size 3x13
+ text run at (164,5) width 3: " "
+ RenderBlock {INPUT} at (170,5) size 12x12
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,432) size 769x39
+ RenderText {#text} at (0,18) size 27x18
+ text run at (0,18) width 27: "text "
+ RenderTextControl {INPUT} at (29,18) size 78x19 [bgcolor=#FFFFFF] [border: (2px inset #000000)]
+ RenderText {#text} at (109,18) size 4x18
+ text run at (109,18) width 4: " "
+ RenderFileUploadControl {INPUT} at (115,19) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderText {#text} at (354,18) size 4x18
+ text run at (354,18) width 4: " "
+ RenderTextControl {TEXTAREA} at (360,2) size 163x28 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {H2} at (0,490) size 769x28
+ RenderText {#text} at (0,0) size 197x28
+ text run at (0,0) width 197: "Pop-up Menu Sizes"
+ RenderBlock {DIV} at (0,537) size 769x29
+ RenderInline {FONT} at (0,0) size 181x28
+ RenderText {#text} at (0,0) size 0x0
+ RenderMenuList {SELECT} at (2,9) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderBR at (0,0) size 0x13 [bgcolor=#FFFFFF]
+ RenderText {#text} at (40,0) size 6x28
+ text run at (40,0) width 6: " "
+ RenderMenuList {SELECT} at (48,9) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderText at (0,0) size 5x13
+ text run at (0,0) width 5: "|"
+ RenderText {#text} at (86,0) size 6x28
+ text run at (86,0) width 6: " "
+ RenderMenuList {SELECT} at (94,9) size 85x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 54x13
+ RenderText at (0,0) size 54x13
+ text run at (0,0) width 54: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,566) size 769x22
+ RenderMenuList {SELECT} at (2,2) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderBR at (0,0) size 0x13 [bgcolor=#FFFFFF]
+ RenderText {#text} at (40,1) size 4x18
+ text run at (40,1) width 4: " "
+ RenderMenuList {SELECT} at (46,2) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderText at (0,0) size 5x13
+ text run at (0,0) width 5: "|"
+ RenderText {#text} at (84,1) size 4x18
+ text run at (84,1) width 4: " "
+ RenderMenuList {SELECT} at (90,2) size 85x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 54x13
+ RenderText at (0,0) size 54x13
+ text run at (0,0) width 54: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {DIV} at (0,588) size 769x22
+ RenderInline {FONT} at (0,0) size 175x13
+ RenderText {#text} at (0,0) size 0x0
+ RenderMenuList {SELECT} at (2,2) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderBR at (0,0) size 0x13 [bgcolor=#FFFFFF]
+ RenderText {#text} at (40,5) size 3x13
+ text run at (40,5) width 3: " "
+ RenderMenuList {SELECT} at (45,2) size 36x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 5x13
+ RenderText at (0,0) size 5x13
+ text run at (0,0) width 5: "|"
+ RenderText {#text} at (83,5) size 3x13
+ text run at (83,5) width 3: " "
+ RenderMenuList {SELECT} at (88,2) size 85x18 [bgcolor=#FFFFFF]
+ RenderBlock (anonymous) at (8,2) size 54x13
+ RenderText at (0,0) size 54x13
+ text run at (0,0) width 54: "xxxxxxxx"
+ RenderText {#text} at (0,0) size 0x0
+layer at (16,242) size 72x13
+ RenderBlock {DIV} at (3,3) size 72x13
+ RenderText {#text} at (1,0) size 49x13
+ text run at (1,0) width 49: "text field"
+layer at (389,242) size 161x26
+ RenderBlock {DIV} at (1,1) size 161x26
+ RenderText {#text} at (3,0) size 44x13
+ text run at (3,0) width 44: "textarea"
+layer at (40,461) size 72x13
+ RenderBlock {DIV} at (3,3) size 72x13
+ RenderText {#text} at (1,0) size 49x13
+ text run at (1,0) width 49: "text field"
+layer at (369,443) size 161x26
+ RenderBlock {DIV} at (1,1) size 161x26
+ RenderText {#text} at (3,0) size 44x13
+ text run at (3,0) width 44: "textarea"
+layer at (0,0) size 1083x585
+ RenderView at (0,0) size 800x585
+layer at (0,0) size 1083x585
+ RenderBlock {HTML} at (0,0) size 800x585
+ RenderBody {BODY} at (8,8) size 784x569
+ RenderTable {TABLE} at (0,0) size 1075x108
+ RenderTableSection {TBODY} at (0,0) size 1075x108
+ RenderTableRow {TR} at (0,2) size 1075x20
+ RenderTableCell {TH} at (2,11) size 83x2 [r=0 c=0 rs=1 cs=1]
+ RenderTableCell {TH} at (87,11) size 245x2 [r=0 c=1 rs=1 cs=1]
+ RenderTableCell {TH} at (334,2) size 245x20 [r=0 c=2 rs=1 cs=1]
+ RenderText {#text} at (78,1) size 89x18
+ text run at (78,1) width 89: "text-align:left"
+ RenderTableCell {TH} at (581,2) size 245x20 [r=0 c=3 rs=1 cs=1]
+ RenderText {#text} at (67,1) size 110x18
+ text run at (67,1) width 110: "text-align:center"
+ RenderTableCell {TH} at (828,2) size 245x20 [r=0 c=4 rs=1 cs=1]
+ RenderText {#text} at (72,1) size 101x18
+ text run at (72,1) width 101: "text-align:right"
+ RenderTableRow {TR} at (0,24) size 1075x26
+ RenderTableCell {TH} at (2,36) size 83x2 [r=1 c=0 rs=1 cs=1]
+ RenderTableCell {TD} at (87,24) size 245x26 [border: (1px solid #000000)] [r=1 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (334,24) size 245x26 [border: (1px solid #000000)] [r=1 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (581,24) size 245x26 [border: (1px solid #000000)] [r=1 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (828,24) size 245x26 [border: (1px solid #000000)] [r=1 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableRow {TR} at (0,52) size 1075x26
+ RenderTableCell {TH} at (2,55) size 83x20 [r=2 c=0 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 81x18
+ text run at (1,1) width 81: "direction:ltr"
+ RenderTableCell {TD} at (87,52) size 245x26 [border: (1px solid #000000)] [r=2 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (334,52) size 245x26 [border: (1px solid #000000)] [r=2 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (581,52) size 245x26 [border: (1px solid #000000)] [r=2 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (828,52) size 245x26 [border: (1px solid #000000)] [r=2 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (0,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableRow {TR} at (0,80) size 1075x26
+ RenderTableCell {TH} at (2,83) size 83x20 [r=3 c=0 rs=1 cs=1]
+ RenderText {#text} at (1,1) size 81x18
+ text run at (1,1) width 81: "direction:rtl"
+ RenderTableCell {TD} at (87,80) size 245x26 [border: (1px solid #000000)] [r=3 c=1 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (159,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (334,80) size 245x26 [border: (1px solid #000000)] [r=3 c=2 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (159,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (581,80) size 245x26 [border: (1px solid #000000)] [r=3 c=3 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (159,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
+ RenderTableCell {TD} at (828,80) size 245x26 [border: (1px solid #000000)] [r=3 c=4 rs=1 cs=1]
+ RenderFileUploadControl {INPUT} at (4,4) size 237x18
+ RenderButton {INPUT} at (159,0) size 78x18 [bgcolor=#C0C0C0]
+ RenderBlock (anonymous) at (8,2) size 62x13
+ RenderText at (0,0) size 62x13
+ text run at (0,0) width 62: "Choose File"
diff --git a/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-actual-win.txt b/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-actual-win.txt
new file mode 100644
index 0000000..d905358
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-actual-win.txt
@@ -0,0 +1,82 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderText {#text} at (0,0) size 763x39
+ text run at (0,0) width 763: "This test verifies that JS access to offsetParent on an element that lacks one, such as the body, doesn't crash. If it didn't crash, it"
+ text run at (0,20) width 46: "passed."
+ RenderText {#text} at (0,0) size 0x0
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {P} at (0,0) size 784x20
+ RenderText {#text} at (0,0) size 107x19
+ text run at (0,0) width 107: "Tests: the bdo tag"
+ RenderBlock {P} at (0,36) size 784x20
+ RenderText {#text} at (0,0) size 313x19
+ text run at (0,0) width 313: "The bdo element overrides the default text direction."
+ RenderBlock {P} at (0,72) size 784x40
+ RenderText {#text} at (0,0) size 757x39
+ text run at (0,0) width 696: "If successful, the first sentence would be backward, and the second sentence regular. There should then be an extra "
+ text run at (696,0) width 61: "blank line,"
+ text run at (0,20) width 622: "followed by a line reading only \"A,\" and finally, a sentence where only the word \"umbrella\" is backward."
+ RenderBlock {HR} at (0,128) size 784x2 [border: (1px inset #000000)]
+ RenderBlock (anonymous) at (0,138) size 784x120
+ RenderBR {BR} at (0,0) size 0x19
+ RenderInline {BDO} at (0,0) size 212x19
+ RenderText {#text} at (0,20) size 212x19
+ text run at (0,20) width 212 RTL override: "This sentence should be backward."
+ RenderText {#text} at (212,20) size 4x19
+ text run at (212,20) width 4: " "
+ RenderBR {BR} at (216,35) size 0x0
+ RenderInline {BDO} at (0,0) size 199x19
+ RenderText {#text} at (0,40) size 199x19
+ text run at (0,40) width 199 LTR override: "This sentence should be forward."
+ RenderText {#text} at (199,40) size 4x19
+ text run at (199,40) width 4: " "
+ RenderBR {BR} at (203,55) size 0x0
+ RenderInline {BDO} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
+ RenderBR {BR} at (0,60) size 0x19
+ RenderInline {BDO} at (0,0) size 11x19
+ RenderText {#text} at (0,80) size 11x19
+ text run at (0,80) width 11 RTL override: "A"
+ RenderText {#text} at (11,80) size 4x19
+ text run at (11,80) width 4: " "
+ RenderBR {BR} at (15,95) size 0x0
+ RenderInline {BDO} at (0,0) size 271x19
+ RenderText {#text} at (0,100) size 25x19
+ text run at (0,100) width 25 LTR override: "My "
+ RenderInline {BDO} at (0,0) size 51x19
+ RenderText {#text} at (25,100) size 51x19
+ text run at (25,100) width 51 RTL override: "umbrella"
+ RenderText {#text} at (76,100) size 195x19
+ text run at (76,100) width 195 LTR override: " sure would be useful in this rain."
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x576
+ RenderBlock {P} at (0,0) size 784x40
+ RenderText {#text} at (0,0) size 242x19
+ text run at (0,0) width 242: "This test checks for a regression against "
+ RenderInline {I} at (0,0) size 752x39
+ RenderInline {A} at (0,0) size 350x19 [color=#0000EE]
+ RenderText {#text} at (242,0) size 350x19
+ text run at (242,0) width 350: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6214"
+ RenderText {#text} at (592,0) size 752x39
+ text run at (592,0) width 160: " text-indent in RTL block"
+ text run at (0,20) width 111: "does the opposite"
+ RenderText {#text} at (111,20) size 4x19
+ text run at (111,20) width 4: "."
+ RenderBlock {HR} at (0,56) size 784x2 [border: (1px inset #000000)]
+ RenderBlock {P} at (0,74) size 784x40 [bgcolor=#00FFFF]
+ RenderText {#text} at (5,0) size 779x39
+ text run at (5,0) width 729: "The first line of this sententce should be indented 50 pixels to the left, but the rest of it should be flush with the normal right"
+ text run at (669,20) width 4 RTL: "."
+ text run at (673,20) width 111: "margin of the page"
diff --git a/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-expected.txt b/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-expected.txt
new file mode 100644
index 0000000..0afa5c7
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/null-offset-parent-expected.txt
@@ -0,0 +1,82 @@
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderText {#text} at (0,0) size 782x36
+ text run at (0,0) width 782: "This test verifies that JS access to offsetParent on an element that lacks one, such as the body, doesn't crash. If it didn't crash,"
+ text run at (0,18) width 58: "it passed."
+ RenderText {#text} at (0,0) size 0x0
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x584
+ RenderBlock {P} at (0,0) size 784x18
+ RenderText {#text} at (0,0) size 111x18
+ text run at (0,0) width 111: "Tests: the bdo tag"
+ RenderBlock {P} at (0,34) size 784x18
+ RenderText {#text} at (0,0) size 328x18
+ text run at (0,0) width 328: "The bdo element overrides the default text direction."
+ RenderBlock {P} at (0,68) size 784x36
+ RenderText {#text} at (0,0) size 762x36
+ text run at (0,0) width 727: "If successful, the first sentence would be backward, and the second sentence regular. There should then be an extra "
+ text run at (727,0) width 35: "blank"
+ text run at (0,18) width 698: "line, followed by a line reading only \"A,\" and finally, a sentence where only the word \"umbrella\" is backward."
+ RenderBlock {HR} at (0,120) size 784x2 [border: (1px inset #000000)]
+ RenderBlock (anonymous) at (0,130) size 784x108
+ RenderBR {BR} at (0,0) size 0x18
+ RenderInline {BDO} at (0,0) size 221x18
+ RenderText {#text} at (0,18) size 221x18
+ text run at (0,18) width 221 RTL override: "This sentence should be backward."
+ RenderText {#text} at (221,18) size 4x18
+ text run at (221,18) width 4: " "
+ RenderBR {BR} at (225,32) size 0x0
+ RenderInline {BDO} at (0,0) size 209x18
+ RenderText {#text} at (0,36) size 209x18
+ text run at (0,36) width 209 LTR override: "This sentence should be forward."
+ RenderText {#text} at (209,36) size 4x18
+ text run at (209,36) width 4: " "
+ RenderBR {BR} at (213,50) size 0x0
+ RenderInline {BDO} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
+ RenderBR {BR} at (0,54) size 0x18
+ RenderInline {BDO} at (0,0) size 12x18
+ RenderText {#text} at (0,72) size 12x18
+ text run at (0,72) width 12 RTL override: "A"
+ RenderText {#text} at (12,72) size 4x18
+ text run at (12,72) width 4: " "
+ RenderBR {BR} at (16,86) size 0x0
+ RenderInline {BDO} at (0,0) size 290x18
+ RenderText {#text} at (0,90) size 26x18
+ text run at (0,90) width 26 LTR override: "My "
+ RenderInline {BDO} at (0,0) size 55x18
+ RenderText {#text} at (26,90) size 55x18
+ text run at (26,90) width 55 RTL override: "umbrella"
+ RenderText {#text} at (81,90) size 209x18
+ text run at (81,90) width 209 LTR override: " sure would be useful in this rain."
+ RenderText {#text} at (0,0) size 0x0
+ RenderText {#text} at (0,0) size 0x0
+layer at (0,0) size 800x600
+ RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+ RenderBlock {HTML} at (0,0) size 800x600
+ RenderBody {BODY} at (8,8) size 784x576
+ RenderBlock {P} at (0,0) size 784x36
+ RenderText {#text} at (0,0) size 253x18
+ text run at (0,0) width 253: "This test checks for a regression against "
+ RenderInline {I} at (0,0) size 757x36
+ RenderInline {A} at (0,0) size 348x18 [color=#0000EE]
+ RenderText {#text} at (253,0) size 348x18
+ text run at (253,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6214"
+ RenderText {#text} at (601,0) size 757x36
+ text run at (601,0) width 156: " text-indent in RTL block"
+ text run at (0,18) width 109: "does the opposite"
+ RenderText {#text} at (109,18) size 4x18
+ text run at (109,18) width 4: "."
+ RenderBlock {HR} at (0,52) size 784x2 [border: (1px inset #000000)]
+ RenderBlock {P} at (0,70) size 784x36 [bgcolor=#00FFFF]
+ RenderText {#text} at (41,0) size 743x36
+ text run at (41,0) width 693: "The first line of this sententce should be indented 50 pixels to the left, but the rest of it should be flush with the"
+ text run at (581,18) width 4 RTL: "."
+ text run at (585,18) width 199: "normal right margin of the page"
diff --git a/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-actual-win.txt b/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-actual-win.txt
new file mode 100644
index 0000000..fbdb37f
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-actual-win.txt
@@ -0,0 +1,75 @@
+layer at (0,0) size 783x1249
+ RenderView at (0,0) size 783x600
+layer at (0,0) size 783x1249
+ RenderBlock {HTML} at (0,0) size 783x1249
+ RenderBody {BODY} at (8,8) size 767x1225
+ RenderBlock (anonymous) at (0,0) size 767x20
+ RenderText {#text} at (0,0) size 254x19
+ text run at (0,0) width 254: "line-height settings not reflected in textarea"
+ RenderBR {BR} at (254,0) size 0x19
+ RenderBlock {P} at (0,36) size 767x267
+ RenderText {#text} at (0,0) size 79x19
+ text run at (0,0) width 79: "TEXTAREA"
+ RenderBR {BR} at (79,0) size 0x19
+ RenderTextControl {TEXTAREA} at (0,20) size 402x202 [bgcolor=#FFFFFF] [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (402,207) size 4x19
+ text run at (402,207) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,227) size 0x19
+ RenderText {#text} at (0,247) size 145x19
+ text run at (0,247) width 145: "PARAGRAPH - works"
+ RenderBlock {P} at (0,319) size 402x202 [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (1,19) size 385x68
+ text run at (1,19) width 385: "Demo text here that wraps a bit and should demonstrate"
+ text run at (1,71) width 181: "the goodness of line-height"
+ RenderBlock (anonymous) at (0,534) size 767x40
+ RenderBR {BR} at (0,0) size 0x19
+ RenderText {#text} at (0,20) size 79x19
+ text run at (0,20) width 79: "DIV - works"
+ RenderBR {BR} at (79,20) size 0x19
+ RenderBlock {DIV} at (0,574) size 402x202 [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (1,19) size 385x68
+ text run at (1,19) width 385: "Demo text here that wraps a bit and should demonstrate"
+ text run at (1,71) width 181: "the goodness of line-height"
+ RenderBlock (anonymous) at (0,776) size 767x449
+ RenderBR {BR} at (0,0) size 0x19
+ RenderBR {BR} at (0,20) size 0x19
+ RenderText {#text} at (0,40) size 119x19
+ text run at (0,40) width 119: "Un-Styled Textarea"
+ RenderBR {BR} at (119,40) size 0x19
+ RenderTextControl {TEXTAREA} at (2,62) size 183x42 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (187,91) size 4x19
+ text run at (187,91) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,111) size 0x19
+ RenderText {#text} at (0,131) size 203x19
+ text run at (0,131) width 203: "Totally Blank Un-Styled Textarea"
+ RenderBR {BR} at (203,131) size 0x19
+ RenderTextControl {TEXTAREA} at (2,153) size 183x42 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (187,182) size 4x19
+ text run at (187,182) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,202) size 0x19
+ RenderText {#text} at (0,222) size 199x19
+ text run at (0,222) width 199: "Totally Blank STYLED Textarea"
+ RenderBR {BR} at (199,222) size 0x19
+ RenderTextControl {TEXTAREA} at (0,242) size 402x202 [bgcolor=#FFFFFF] [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {P} at (0,1241) size 767x0
+layer at (9,65) size 400x200
+ RenderBlock {DIV} at (1,1) size 400x200
+ RenderText {#text} at (3,18) size 390x68
+ text run at (3,18) width 390: "Demo text here that wraps a bit and should demonstrate "
+ text run at (3,70) width 181: "the goodness of line-height"
+layer at (11,847) size 181x40 clip at (11,847) size 164x40 scrollHeight 79
+ RenderBlock {DIV} at (1,1) size 181x40
+ RenderText {#text} at (3,0) size 158x79
+ text run at (3,0) width 123: "Demo text here that "
+ text run at (3,20) width 140: "wraps a bit and should "
+ text run at (3,40) width 157: "demonstrate the goodness"
+ text run at (160,40) width 1: " "
+ text run at (3,60) width 77: "of line-height"
+layer at (11,938) size 181x40
+ RenderBlock {DIV} at (1,1) size 181x40
+layer at (9,1027) size 400x200
+ RenderBlock {DIV} at (1,1) size 400x200
diff --git a/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-expected.txt b/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-expected.txt
new file mode 100644
index 0000000..1de6aae
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/difftests/textAreaLineHeight-expected.txt
@@ -0,0 +1,74 @@
+layer at (0,0) size 785x1191
+ RenderView at (0,0) size 785x600
+layer at (0,0) size 785x1191
+ RenderBlock {HTML} at (0,0) size 785x1191
+ RenderBody {BODY} at (8,8) size 769x1167
+ RenderBlock (anonymous) at (0,0) size 769x18
+ RenderText {#text} at (0,0) size 269x18
+ text run at (0,0) width 269: "line-height settings not reflected in textarea"
+ RenderBR {BR} at (269,0) size 0x18
+ RenderBlock {P} at (0,34) size 769x260
+ RenderText {#text} at (0,0) size 87x18
+ text run at (0,0) width 87: "TEXTAREA"
+ RenderBR {BR} at (87,0) size 0x18
+ RenderTextControl {TEXTAREA} at (0,18) size 402x202 [bgcolor=#FFFFFF] [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (402,206) size 4x18
+ text run at (402,206) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,224) size 0x18
+ RenderText {#text} at (0,242) size 152x18
+ text run at (0,242) width 152: "PARAGRAPH - works"
+ RenderBlock {P} at (0,310) size 402x202 [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (1,19) size 382x68
+ text run at (1,19) width 382: "Demo text here that wraps a bit and should demonstrate"
+ text run at (1,71) width 182: "the goodness of line-height"
+ RenderBlock (anonymous) at (0,525) size 769x36
+ RenderBR {BR} at (0,0) size 0x18
+ RenderText {#text} at (0,18) size 81x18
+ text run at (0,18) width 81: "DIV - works"
+ RenderBR {BR} at (81,18) size 0x18
+ RenderBlock {DIV} at (0,561) size 402x202 [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (1,19) size 382x68
+ text run at (1,19) width 382: "Demo text here that wraps a bit and should demonstrate"
+ text run at (1,71) width 182: "the goodness of line-height"
+ RenderBlock (anonymous) at (0,763) size 769x404
+ RenderBR {BR} at (0,0) size 0x18
+ RenderBR {BR} at (0,18) size 0x18
+ RenderText {#text} at (0,36) size 124x18
+ text run at (0,36) width 124: "Un-Styled Textarea"
+ RenderBR {BR} at (124,36) size 0x18
+ RenderTextControl {TEXTAREA} at (2,56) size 163x28 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (167,72) size 4x18
+ text run at (167,72) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,90) size 0x18
+ RenderText {#text} at (0,108) size 215x18
+ text run at (0,108) width 215: "Totally Blank Un-Styled Textarea"
+ RenderBR {BR} at (215,108) size 0x18
+ RenderTextControl {TEXTAREA} at (2,128) size 163x28 [bgcolor=#FFFFFF] [border: (1px solid #000000)]
+ RenderText {#text} at (167,144) size 4x18
+ text run at (167,144) width 4: " "
+ RenderBR {BR} at (0,0) size 0x0
+ RenderBR {BR} at (0,162) size 0x18
+ RenderText {#text} at (0,180) size 213x18
+ text run at (0,180) width 213: "Totally Blank STYLED Textarea"
+ RenderBR {BR} at (213,180) size 0x18
+ RenderTextControl {TEXTAREA} at (0,198) size 402x202 [bgcolor=#FFFFFF] [border: (1px dotted #C0C0C0)]
+ RenderText {#text} at (0,0) size 0x0
+ RenderBlock {P} at (0,1183) size 769x0
+layer at (9,61) size 400x200
+ RenderBlock {DIV} at (1,1) size 400x200
+ RenderText {#text} at (3,18) size 387x68
+ text run at (3,18) width 387: "Demo text here that wraps a bit and should demonstrate "
+ text run at (3,70) width 182: "the goodness of line-height"
+layer at (11,828) size 161x26 clip at (11,828) size 146x26 scrollHeight 52
+ RenderBlock {DIV} at (1,1) size 161x26
+ RenderText {#text} at (3,0) size 130x52
+ text run at (3,0) width 112: "Demo text here that "
+ text run at (3,13) width 126: "wraps a bit and should "
+ text run at (3,26) width 92: "demonstrate the "
+ text run at (3,39) width 130: "goodness of line-height"
+layer at (11,900) size 161x26
+ RenderBlock {DIV} at (1,1) size 161x26
+layer at (9,970) size 400x200
+ RenderBlock {DIV} at (1,1) size 400x200
diff --git a/webkit/tools/layout_tests/testdata/expected-crashes-new-passing.txt b/webkit/tools/layout_tests/testdata/expected-crashes-new-passing.txt
new file mode 100644
index 0000000..97ec414
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-crashes-new-passing.txt
@@ -0,0 +1,2 @@
+fast/bar/crash2.html
+fast/foo/crash1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-crashes-new-test.txt b/webkit/tools/layout_tests/testdata/expected-crashes-new-test.txt
new file mode 100644
index 0000000..d6d3da2
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-crashes-new-test.txt
@@ -0,0 +1,4 @@
+fast/bar/betz/crash3.html
+fast/bar/crash2.html
+fast/foo/crash1.html
+new-test.html
diff --git a/webkit/tools/layout_tests/testdata/expected-crashes.txt b/webkit/tools/layout_tests/testdata/expected-crashes.txt
new file mode 100644
index 0000000..ca65a65
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-crashes.txt
@@ -0,0 +1,3 @@
+fast/bar/betz/crash3.html
+fast/bar/crash2.html
+fast/foo/crash1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-failures-added.txt b/webkit/tools/layout_tests/testdata/expected-failures-added.txt
new file mode 100644
index 0000000..a327425
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-failures-added.txt
@@ -0,0 +1,4 @@
+fast/bar/betz/fail3.html
+fast/bar/fail2.html
+fast/foo/fail1.html
+fast/pass1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-failures-new-crash.txt b/webkit/tools/layout_tests/testdata/expected-failures-new-crash.txt
new file mode 100644
index 0000000..7c25263
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-failures-new-crash.txt
@@ -0,0 +1,4 @@
+fast/bar/betz/crash3.html
+fast/bar/betz/fail3.html
+fast/bar/fail2.html
+fast/foo/fail1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-failures-new-passing.txt b/webkit/tools/layout_tests/testdata/expected-failures-new-passing.txt
new file mode 100644
index 0000000..d2d2e79
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-failures-new-passing.txt
@@ -0,0 +1,2 @@
+fast/bar/betz/fail3.html
+fast/foo/fail1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-failures-new-test.txt b/webkit/tools/layout_tests/testdata/expected-failures-new-test.txt
new file mode 100644
index 0000000..9492214
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-failures-new-test.txt
@@ -0,0 +1,4 @@
+fast/bar/betz/fail3.html
+fast/bar/fail2.html
+fast/foo/fail1.html
+new-test.html
diff --git a/webkit/tools/layout_tests/testdata/expected-failures.txt b/webkit/tools/layout_tests/testdata/expected-failures.txt
new file mode 100644
index 0000000..0e637e1
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-failures.txt
@@ -0,0 +1,3 @@
+fast/bar/betz/fail3.html
+fast/bar/fail2.html
+fast/foo/fail1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-passing-new-baseline.txt b/webkit/tools/layout_tests/testdata/expected-passing-new-baseline.txt
new file mode 100644
index 0000000..de8a4b6
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-passing-new-baseline.txt
@@ -0,0 +1 @@
+fast/foo/pass2.html
diff --git a/webkit/tools/layout_tests/testdata/expected-passing-new-passing.txt b/webkit/tools/layout_tests/testdata/expected-passing-new-passing.txt
new file mode 100644
index 0000000..3bac884
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-passing-new-passing.txt
@@ -0,0 +1,3 @@
+fast/bar/betz/crash3.html
+fast/foo/pass2.html
+fast/pass1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-passing-new-passing2.txt b/webkit/tools/layout_tests/testdata/expected-passing-new-passing2.txt
new file mode 100644
index 0000000..72acc8a
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-passing-new-passing2.txt
@@ -0,0 +1,3 @@
+fast/bar/fail2.html
+fast/foo/pass2.html
+fast/pass1.html
diff --git a/webkit/tools/layout_tests/testdata/expected-passing-new-test.txt b/webkit/tools/layout_tests/testdata/expected-passing-new-test.txt
new file mode 100644
index 0000000..5b5b0ad
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-passing-new-test.txt
@@ -0,0 +1,3 @@
+fast/foo/pass2.html
+fast/pass1.html
+new-test.html
diff --git a/webkit/tools/layout_tests/testdata/expected-passing.txt b/webkit/tools/layout_tests/testdata/expected-passing.txt
new file mode 100644
index 0000000..2cdebb4
--- /dev/null
+++ b/webkit/tools/layout_tests/testdata/expected-passing.txt
@@ -0,0 +1,2 @@
+fast/foo/pass2.html
+fast/pass1.html