diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-27 00:20:51 +0000 |
commit | f5b16fed647e941aa66933178da85db2860d639b (patch) | |
tree | f00e9856c04aad3b558a140955e7674add33f051 /webkit/tools/layout_tests | |
parent | 920c091ac3ee15079194c82ae8a7a18215f3f23c (diff) | |
download | chromium_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')
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(" %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 |