2 # Copyright (C) 2010 Google Inc. All rights reserved.
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following disclaimer
12 # in the documentation and/or other materials provided with the
14 # * Neither the name of Google Inc. nor the names of its
15 # contributors may be used to endorse or promote products derived from
16 # this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 """Defines the interface TestTypeBase which other test types inherit from.
37 _log = logging.getLogger("webkitpy.layout_tests.test_types.test_type_base")
40 # Python bug workaround. See the wdiff code in WriteOutputFiles for an
42 _wdiff_available = True
45 class TestTypeBase(object):
47 # Filename pieces when writing failures to the test results directory.
48 FILENAME_SUFFIX_ACTUAL = "-actual"
49 FILENAME_SUFFIX_EXPECTED = "-expected"
50 FILENAME_SUFFIX_DIFF = "-diff"
51 FILENAME_SUFFIX_WDIFF = "-wdiff.html"
52 FILENAME_SUFFIX_PRETTY_PATCH = "-pretty-diff.html"
53 FILENAME_SUFFIX_COMPARE = "-diff.png"
55 def __init__(self, port, root_output_dir):
56 """Initialize a TestTypeBase object.
59 port: object implementing port-specific information and methods
60 root_output_dir: The unix style path to the output dir.
62 self._root_output_dir = root_output_dir
65 def _make_output_directory(self, filename):
66 """Creates the output directory (if needed) for a given test
68 fs = self._port._filesystem
69 output_filename = fs.join(self._root_output_dir,
70 self._port.relative_test_filename(filename))
71 fs.maybe_make_directory(fs.dirname(output_filename))
73 def output_filename(self, filename, modifier):
74 """Returns a filename inside the output dir that contains modifier.
76 For example, if filename is c:/.../fast/dom/foo.html and modifier is
77 "-expected.txt", the return value is
78 c:/cygwin/tmp/layout-test-results/fast/dom/foo-expected.txt
81 filename: absolute filename to test file
82 modifier: a string to replace the extension of filename with
85 The absolute windows path to the output filename
87 fs = self._port._filesystem
88 output_filename = fs.join(self._root_output_dir,
89 self._port.relative_test_filename(filename))
90 return fs.splitext(output_filename)[0] + modifier
92 def compare_output(self, port, filename, options, actual_driver_output,
93 expected_driver_output):
94 """Method that compares the output from the test with the
97 This is an abstract method to be implemented by all sub classes.
100 port: object implementing port-specific information and methods
101 filename: absolute filename to test file
102 options: command line argument object from optparse
103 actual_driver_output: a DriverOutput object which represents actual test
105 expected_driver_output: a ExpectedDriverOutput object which represents a
109 a list of TestFailure objects, empty if the test passes
111 raise NotImplementedError
113 def _write_into_file_at_path(self, file_path, contents, encoding):
114 """This method assumes that byte_array is already encoded
115 into the right format."""
116 fs = self._port._filesystem
118 fs.write_binary_file(file_path, contents)
120 fs.write_text_file(file_path, contents)
122 def write_output_files(self, filename, file_type,
123 output, expected, encoding,
124 print_text_diffs=False):
125 """Writes the test output, the expected output and optionally the diff
126 between the two to files in the results directory.
128 The full output filename of the actual, for example, will be
129 <filename>-actual<file_type>
134 filename: The test filename
135 file_type: A string describing the test output file type, e.g. ".txt"
136 output: A string containing the test output
137 expected: A string containing the expected test output
138 print_text_diffs: True for text diffs. (FIXME: We should be able to get this from the file type?)
140 self._make_output_directory(filename)
141 actual_filename = self.output_filename(filename, self.FILENAME_SUFFIX_ACTUAL + file_type)
142 expected_filename = self.output_filename(filename, self.FILENAME_SUFFIX_EXPECTED + file_type)
143 # FIXME: This function is poorly designed. We should be passing in some sort of
144 # encoding information from the callers.
146 self._write_into_file_at_path(actual_filename, output, encoding)
148 self._write_into_file_at_path(expected_filename, expected, encoding)
150 if not output or not expected:
153 if not print_text_diffs:
156 # Note: We pass encoding=None for all diff writes, as we treat diff
157 # output as binary. Diff output may contain multiple files in
158 # conflicting encodings.
159 diff = self._port.diff_text(expected, output, expected_filename, actual_filename)
160 diff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_DIFF + file_type)
161 self._write_into_file_at_path(diff_filename, diff, encoding=None)
163 # Shell out to wdiff to get colored inline diffs.
164 wdiff = self._port.wdiff_text(expected_filename, actual_filename)
165 wdiff_filename = self.output_filename(filename, self.FILENAME_SUFFIX_WDIFF)
166 self._write_into_file_at_path(wdiff_filename, wdiff, encoding=None)
168 # Use WebKit's PrettyPatch.rb to get an HTML diff.
169 pretty_patch = self._port.pretty_patch_text(diff_filename)
170 pretty_patch_filename = self.output_filename(filename, self.FILENAME_SUFFIX_PRETTY_PATCH)
171 self._write_into_file_at_path(pretty_patch_filename, pretty_patch, encoding=None)