[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.19-706-ge5415e9
dpranke at chromium.org
dpranke at chromium.org
Thu Feb 4 21:33:03 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit 3aea660682fc35a504472c86206ecccad2310904
Author: dpranke at chromium.org <dpranke at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Sat Jan 30 01:17:08 2010 +0000
2010-01-29 Dirk Pranke <dpranke at chromium.org>
Reviewed by Eric Siedel.
Add in the second block of python code for the Chromium port
of run-webkit-tests. These files execute different diffs to classify
the various types of failures from a test.
* Scripts/webkitpy/layout_tests/test_types: Added.
* Scripts/webkitpy/layout_tests/test_types/__init__.py: Added.
* Scripts/webkitpy/layout_tests/test_types/fuzzy_image_diff.py: Added.
* Scripts/webkitpy/layout_tests/test_types/image_diff.py: Added.
* Scripts/webkitpy/layout_tests/test_types/test_type_base.py: Added.
* Scripts/webkitpy/layout_tests/test_types/text_diff.py: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54093 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 57360d9..fbcd93f 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -2,6 +2,21 @@
Reviewed by Eric Siedel.
+ Add in the second block of python code for the Chromium port
+ of run-webkit-tests. These files execute different diffs to classify
+ the various types of failures from a test.
+
+ * Scripts/webkitpy/layout_tests/test_types: Added.
+ * Scripts/webkitpy/layout_tests/test_types/__init__.py: Added.
+ * Scripts/webkitpy/layout_tests/test_types/fuzzy_image_diff.py: Added.
+ * Scripts/webkitpy/layout_tests/test_types/image_diff.py: Added.
+ * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: Added.
+ * Scripts/webkitpy/layout_tests/test_types/text_diff.py: Added.
+
+2010-01-29 Dirk Pranke <dpranke at chromium.org>
+
+ Reviewed by Eric Siedel.
+
Check in the first part of the Chromium Python port of the
run-webkit-tests test driver. The files under
layout_tests/layout_layout constitute most of the implementation;
diff --git a/BugsSite/data/mail b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/__init__.py
similarity index 100%
copy from BugsSite/data/mail
copy to WebKitTools/Scripts/webkitpy/layout_tests/test_types/__init__.py
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/fuzzy_image_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/fuzzy_image_diff.py
new file mode 100644
index 0000000..134b507
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/fuzzy_image_diff.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 The Chromium Authors. 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 Chromium name 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 using
+fuzzy matching.
+"""
+
+import errno
+import logging
+import os
+import shutil
+import subprocess
+
+from layout_package import path_utils
+from layout_package import test_failures
+from test_types import test_type_base
+
+
+class FuzzyImageDiff(test_type_base.TestTypeBase):
+
+ def compare_output(self, filename, proc, output, test_args, target):
+ """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
+
+ expected_png_file = path_utils.expected_filename(filename, '.png')
+
+ if test_args.show_sources:
+ logging.debug('Using %s' % expected_png_file)
+
+ # Also report a missing expected PNG file.
+ if not os.path.isfile(expected_png_file):
+ failures.append(test_failures.FailureMissingImage(self))
+
+ # Run the fuzzymatcher
+ r = subprocess.call([path_utils.fuzzy_match_path(),
+ test_args.png_path, expected_png_file])
+ if r != 0:
+ failures.append(test_failures.FailureFuzzyFailure(self))
+
+ return failures
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
new file mode 100644
index 0000000..b0bf189
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
@@ -0,0 +1,224 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 The Chromium Authors. 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 Chromium name 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 logging
+import os
+import shutil
+import subprocess
+
+from layout_package import path_utils
+from layout_package import test_failures
+from test_types import test_type_base
+
+# Cache whether we have the image_diff executable available.
+_compare_available = True
+_compare_msg_printed = False
+
+
+class ImageDiff(test_type_base.TestTypeBase):
+
+ def _copy_output_png(self, test_filename, source_image, extension):
+ """Copies result files into the output directory with appropriate
+ names.
+
+ Args:
+ test_filename: the test filename
+ source_file: path to the image file (either actual or expected)
+ extension: extension to indicate -actual.png or -expected.png
+ """
+ self._make_output_directory(test_filename)
+ dest_image = self.output_filename(test_filename, extension)
+
+ try:
+ shutil.copyfile(source_image, dest_image)
+ except IOError, e:
+ # A missing expected PNG has already been recorded as an error.
+ if errno.ENOENT != e.errno:
+ raise
+
+ def _save_baseline_files(self, filename, png_path, checksum):
+ """Saves new baselines for the PNG and checksum.
+
+ Args:
+ filename: test filename
+ 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._save_baseline_data(filename, png_data, ".png")
+ self._save_baseline_data(filename, checksum, ".checksum")
+
+ def _create_image_diff(self, filename, target):
+ """Creates the visual diff of the expected/actual PNGs.
+
+ Args:
+ filename: the name of the test
+ target: Debug or Release
+ """
+ diff_filename = self.output_filename(filename,
+ self.FILENAME_SUFFIX_COMPARE)
+ actual_filename = self.output_filename(filename,
+ self.FILENAME_SUFFIX_ACTUAL + '.png')
+ expected_filename = self.output_filename(filename,
+ self.FILENAME_SUFFIX_EXPECTED + '.png')
+
+ global _compare_available
+ cmd = ''
+
+ try:
+ executable = path_utils.image_diff_path(target)
+ cmd = [executable, '--diff', actual_filename, expected_filename,
+ diff_filename]
+ except Exception, e:
+ _compare_available = False
+
+ result = 1
+ if _compare_available:
+ try:
+ result = subprocess.call(cmd)
+ except OSError, e:
+ if e.errno == errno.ENOENT or e.errno == errno.EACCES:
+ _compare_available = False
+ else:
+ raise e
+ except ValueError:
+ # work around a race condition in Python 2.4's implementation
+ # of subprocess.Popen
+ pass
+
+ global _compare_msg_printed
+
+ if not _compare_available and not _compare_msg_printed:
+ _compare_msg_printed = True
+ print('image_diff not found. Make sure you have a ' + target +
+ ' build of the image_diff executable.')
+
+ return result
+
+ def compare_output(self, filename, proc, output, test_args, target):
+ """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._save_baseline_files(filename, test_args.png_path,
+ test_args.hash)
+ return failures
+
+ # Compare hashes.
+ expected_hash_file = path_utils.expected_filename(filename,
+ '.checksum')
+ expected_png_file = path_utils.expected_filename(filename, '.png')
+
+ if test_args.show_sources:
+ logging.debug('Using %s' % expected_hash_file)
+ logging.debug('Using %s' % expected_png_file)
+
+ try:
+ expected_hash = open(expected_hash_file, "r").read()
+ except IOError, e:
+ if errno.ENOENT != e.errno:
+ raise
+ expected_hash = ''
+
+
+ if not os.path.isfile(expected_png_file):
+ # Report a missing expected PNG file.
+ self.write_output_files(filename, '', '.checksum', test_args.hash,
+ expected_hash, diff=False, wdiff=False)
+ self._copy_output_png(filename, test_args.png_path, '-actual.png')
+ failures.append(test_failures.FailureMissingImage(self))
+ return failures
+ elif test_args.hash == expected_hash:
+ # Hash matched (no diff needed, okay to return).
+ return failures
+
+
+ self.write_output_files(filename, '', '.checksum', test_args.hash,
+ expected_hash, diff=False, wdiff=False)
+ self._copy_output_png(filename, test_args.png_path, '-actual.png')
+ self._copy_output_png(filename, expected_png_file, '-expected.png')
+
+ # Even though we only use result in one codepath below but we
+ # still need to call CreateImageDiff for other codepaths.
+ result = self._create_image_diff(filename, target)
+ if expected_hash == '':
+ failures.append(test_failures.FailureMissingImageHash(self))
+ elif test_args.hash != expected_hash:
+ # Hashes don't match, so see if the images match. If they do, then
+ # the hash is wrong.
+ if result == 0:
+ failures.append(test_failures.FailureImageHashIncorrect(self))
+ else:
+ failures.append(test_failures.FailureImageHashMismatch(self))
+
+ return failures
+
+ def diff_files(self, file1, file2):
+ """Diff two image files.
+
+ Args:
+ file1, file2: full paths of the files to compare.
+
+ Returns:
+ True if two files are different.
+ False otherwise.
+ """
+
+ try:
+ executable = path_utils.image_diff_path('Debug')
+ except Exception, e:
+ logging.warn('Failed to find image diff executable.')
+ return True
+
+ cmd = [executable, file1, file2]
+ result = 1
+ try:
+ result = subprocess.call(cmd)
+ except OSError, e:
+ logging.warn('Failed to compare image diff: %s', e)
+ return True
+
+ return result == 1
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
new file mode 100644
index 0000000..334ae70
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 The Chromium Authors. 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 Chromium name 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 cgi
+import difflib
+import errno
+import logging
+import os.path
+import subprocess
+
+from layout_package import path_utils
+
+
+class TestArguments(object):
+ """Struct-like wrapper for additional arguments needed by
+ specific tests."""
+ # Whether to save new baseline results.
+ new_baseline = False
+
+ # Path to the actual PNG file generated by pixel tests
+ png_path = None
+
+ # Value of checksum generated by pixel tests.
+ hash = None
+
+ # Whether to use wdiff to generate by-word diffs.
+ wdiff = False
+
+ # Whether to report the locations of the expected result files used.
+ show_sources = False
+
+# Python bug workaround. See the wdiff code in WriteOutputFiles for an
+# explanation.
+_wdiff_available = True
+
+
+class TestTypeBase(object):
+
+ # Filename pieces when writing failures to the test results directory.
+ FILENAME_SUFFIX_ACTUAL = "-actual"
+ FILENAME_SUFFIX_EXPECTED = "-expected"
+ FILENAME_SUFFIX_DIFF = "-diff"
+ FILENAME_SUFFIX_WDIFF = "-wdiff.html"
+ FILENAME_SUFFIX_COMPARE = "-diff.png"
+
+ def __init__(self, platform, root_output_dir):
+ """Initialize a TestTypeBase object.
+
+ Args:
+ platform: the platform (e.g., 'chromium-mac-leopard')
+ identifying the platform-specific results to be used.
+ root_output_dir: The unix style path to the output dir.
+ """
+ self._root_output_dir = root_output_dir
+ self._platform = platform
+
+ def _make_output_directory(self, filename):
+ """Creates the output directory (if needed) for a given test
+ filename."""
+ output_filename = os.path.join(self._root_output_dir,
+ path_utils.relative_test_filename(filename))
+ path_utils.maybe_make_directory(os.path.split(output_filename)[0])
+
+ def _save_baseline_data(self, filename, data, modifier):
+ """Saves a new baseline file into the platform directory.
+
+ The file will be named simply "<test>-expected<modifier>", suitable for
+ use as the expected results in a later run.
+
+ Args:
+ filename: path to the test file
+ data: result to be saved as the new baseline
+ modifier: type of the result file, e.g. ".txt" or ".png"
+ """
+ relative_dir = os.path.dirname(
+ path_utils.relative_test_filename(filename))
+ output_dir = os.path.join(
+ path_utils.chromium_baseline_path(self._platform), relative_dir)
+ output_file = os.path.basename(os.path.splitext(filename)[0] +
+ self.FILENAME_SUFFIX_EXPECTED + modifier)
+
+ path_utils.maybe_make_directory(output_dir)
+ output_path = os.path.join(output_dir, output_file)
+ logging.debug('writing new baseline to "%s"' % (output_path))
+ open(output_path, "wb").write(data)
+
+ def output_filename(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.relative_test_filename(filename))
+ return os.path.splitext(output_filename)[0] + modifier
+
+ def compare_output(self, filename, proc, output, test_args, target):
+ """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
+ target: Debug or Release
+
+ Return:
+ a list of TestFailure objects, empty if the test passes
+ """
+ raise NotImplemented
+
+ def write_output_files(self, filename, test_type, file_type, output,
+ expected, diff=True, wdiff=False):
+ """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<file_type>
+ For instance,
+ my_test-simp-actual.txt
+
+ Args:
+ filename: The test filename
+ test_type: A string describing the test type, e.g. "simp"
+ file_type: 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
+ wdiff: if True, write an HTML file containing word-by-word diffs
+ """
+ self._make_output_directory(filename)
+ actual_filename = self.output_filename(filename,
+ test_type + self.FILENAME_SUFFIX_ACTUAL + file_type)
+ expected_filename = self.output_filename(filename,
+ test_type + self.FILENAME_SUFFIX_EXPECTED + file_type)
+ if output:
+ open(actual_filename, "wb").write(output)
+ if expected:
+ open(expected_filename, "wb").write(expected)
+
+ if not output or not expected:
+ return
+
+ if diff:
+ diff = difflib.unified_diff(expected.splitlines(True),
+ output.splitlines(True),
+ expected_filename,
+ actual_filename)
+
+ diff_filename = self.output_filename(filename,
+ test_type + self.FILENAME_SUFFIX_DIFF + file_type)
+ open(diff_filename, "wb").write(''.join(diff))
+
+ if wdiff:
+ # Shell out to wdiff to get colored inline diffs.
+ executable = path_utils.wdiff_path()
+ cmd = [executable,
+ '--start-delete=##WDIFF_DEL##',
+ '--end-delete=##WDIFF_END##',
+ '--start-insert=##WDIFF_ADD##',
+ '--end-insert=##WDIFF_END##',
+ expected_filename,
+ actual_filename]
+ filename = self.output_filename(filename,
+ test_type + self.FILENAME_SUFFIX_WDIFF)
+
+ global _wdiff_available
+
+ try:
+ # Python's Popen has a bug that causes any pipes opened to a
+ # process that can't be executed to be leaked. Since this
+ # code is specifically designed to tolerate exec failures
+ # to gracefully handle cases where wdiff is not installed,
+ # the bug results in a massive file descriptor leak. As a
+ # workaround, if an exec failure is ever experienced for
+ # wdiff, assume it's not available. This will leak one
+ # file descriptor but that's better than leaking each time
+ # wdiff would be run.
+ #
+ # http://mail.python.org/pipermail/python-list/
+ # 2008-August/505753.html
+ # http://bugs.python.org/issue3210
+ #
+ # It also has a threading bug, so we don't output wdiff if
+ # the Popen raises a ValueError.
+ # http://bugs.python.org/issue1236
+ if _wdiff_available:
+ wdiff = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE).communicate()[0]
+ wdiff_failed = False
+
+ except OSError, e:
+ if (e.errno == errno.ENOENT or e.errno == errno.EACCES or
+ e.errno == errno.ECHILD):
+ _wdiff_available = False
+ else:
+ raise e
+ except ValueError, e:
+ wdiff_failed = True
+
+ out = open(filename, 'wb')
+
+ if not _wdiff_available:
+ out.write(
+ "wdiff not installed.<br/> "
+ "If you're running OS X, you can install via macports."
+ "<br/>"
+ "If running Ubuntu linux, you can run "
+ "'sudo apt-get install wdiff'.")
+ elif wdiff_failed:
+ out.write('wdiff failed due to running with multiple '
+ 'test_shells in parallel.')
+ else:
+ wdiff = cgi.escape(wdiff)
+ wdiff = wdiff.replace('##WDIFF_DEL##', '<span class=del>')
+ wdiff = wdiff.replace('##WDIFF_ADD##', '<span class=add>')
+ wdiff = wdiff.replace('##WDIFF_END##', '</span>')
+ out.write('<head><style>.del { background: #faa; } ')
+ out.write('.add { background: #afa; }</style></head>')
+ out.write('<pre>' + wdiff + '</pre>')
+
+ out.close()
diff --git a/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py
new file mode 100644
index 0000000..8cff9e6
--- /dev/null
+++ b/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+# Copyright (C) 2010 The Chromium Authors. 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 Chromium name 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 logging
+import os.path
+
+from layout_package import path_utils
+from layout_package import test_failures
+from test_types import test_type_base
+
+
+def is_render_tree_dump(data):
+ """Returns true if data appears to be a render tree dump as opposed to a
+ plain text dump."""
+ return data.find("RenderView at (0,0)") != -1
+
+
+class TestTextDiff(test_type_base.TestTypeBase):
+
+ def get_normalized_output_text(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 get_normalized_expected_text(self, filename, show_sources):
+ """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.
+ expected_filename = path_utils.expected_filename(filename, '.txt')
+ if show_sources:
+ logging.debug('Using %s' % expected_filename)
+
+ return self.get_normalized_text(expected_filename)
+
+ def get_normalized_text(self, filename):
+ try:
+ text = open(filename).read()
+ except IOError, e:
+ if errno.ENOENT != e.errno:
+ raise
+ return ''
+
+ # Normalize line endings
+ return text.strip("\r\n").replace("\r\n", "\n") + "\n"
+
+ def compare_output(self, filename, proc, output, test_args, target):
+ """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.new_baseline:
+ self._save_baseline_data(filename, output, ".txt")
+ return failures
+
+ # Normalize text to diff
+ output = self.get_normalized_output_text(output)
+ expected = self.get_normalized_expected_text(filename,
+ test_args.show_sources)
+
+ # Write output files for new tests, too.
+ if output != expected:
+ # Text doesn't match, write output files.
+ self.write_output_files(filename, "", ".txt", output, expected,
+ diff=True, wdiff=True)
+
+ if expected == '':
+ failures.append(test_failures.FailureMissingResult(self))
+ else:
+ failures.append(test_failures.FailureTextMismatch(self, True))
+
+ return failures
+
+ def diff_files(self, file1, file2):
+ """Diff two text files.
+
+ Args:
+ file1, file2: full paths of the files to compare.
+
+ Returns:
+ True if two files are different.
+ False otherwise.
+ """
+
+ return (self.get_normalized_text(file1) !=
+ self.get_normalized_text(file2))
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list