Changeset 72249 in webkit
- Timestamp:
- Nov 17, 2010 3:02:39 PM (13 years ago)
- Location:
- trunk/WebKitTools
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebKitTools/ChangeLog
r72245 r72249 1 2010-11-17 Hayato Ito <hayato@chromium.org> 2 3 Refactor TestTypeBase.compare_output(). 4 5 Introduce a TestOutput class and update compare_output() of each test 6 types so that they can take both actual and expected TestOutput objects. 7 8 https://bugs.webkit.org/show_bug.cgi?id=49431 9 10 * Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py: 11 * Scripts/webkitpy/layout_tests/layout_package/test_output.py: Added. 12 * Scripts/webkitpy/layout_tests/port/base.py: 13 * Scripts/webkitpy/layout_tests/port/chromium.py: 14 * Scripts/webkitpy/layout_tests/port/dryrun.py: 15 * Scripts/webkitpy/layout_tests/port/test.py: 16 * Scripts/webkitpy/layout_tests/port/webkit.py: 17 * Scripts/webkitpy/layout_tests/run_webkit_tests.py: 18 * Scripts/webkitpy/layout_tests/test_types/image_diff.py: 19 * Scripts/webkitpy/layout_tests/test_types/test_type_base.py: 20 * Scripts/webkitpy/layout_tests/test_types/text_diff.py: 21 1 22 2010-11-17 Adam Roben <aroben@apple.com> 2 23 -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/layout_package/dump_render_tree_thread.py
r72149 r72249 52 52 53 53 import test_failures 54 import test_output 54 55 import test_results 55 56 … … 75 76 76 77 78 def _expected_test_output(port, filename): 79 """Returns an expected TestOutput object.""" 80 return test_output.TestOutput(port.expected_text(filename), 81 port.expected_image(filename), 82 port.expected_checksum(filename)) 83 77 84 def _process_output(port, options, test_input, test_types, test_args, 78 crash, timeout, test_run_time, actual_checksum, 79 output, error): 85 test_output): 80 86 """Receives the output from a DumpRenderTree process, subjects it to a 81 87 number of tests, and returns a list of failure types the test produced. … … 88 94 test_types: list of test types to subject the output to 89 95 test_args: arguments to be passed to each test 96 test_output: a TestOutput object containing the output of the test 90 97 91 98 Returns: a TestResult object … … 93 100 failures = [] 94 101 95 # Some test args, such as the image hash, may be added or changed on a 96 # test-by-test basis. 97 local_test_args = copy.copy(test_args) 98 99 local_test_args.hash = actual_checksum 100 101 if crash: 102 if test_output.crash: 102 103 failures.append(test_failures.FailureCrash()) 103 if t imeout:104 if test_output.timeout: 104 105 failures.append(test_failures.FailureTimeout()) 105 106 106 if crash: 107 _log.debug("Stacktrace for %s:\n%s" % (test_input.filename, error)) 107 if test_output.crash: 108 _log.debug("Stacktrace for %s:\n%s" % (test_input.filename, 109 test_output.error)) 108 110 # Strip off "file://" since RelativeTestFilename expects 109 111 # filesystem paths. … … 114 116 port.maybe_make_directory(os.path.split(filename)[0]) 115 117 with codecs.open(filename, "wb", "utf-8") as file: 116 file.write(error) 117 elif error: 118 _log.debug("Previous test output stderr lines:\n%s" % error) 118 file.write(test_output.error) 119 elif test_output.error: 120 _log.debug("Previous test output stderr lines:\n%s" % test_output.error) 121 122 expected_test_output = _expected_test_output(port, test_input.filename) 119 123 120 124 # Check the output and save the results. … … 124 128 start_diff_time = time.time() 125 129 new_failures = test_type.compare_output(port, test_input.filename, 126 output, local_test_args,127 options.configuration)130 test_args, test_output, 131 expected_test_output) 128 132 # Don't add any more failures if we already have a crash, so we don't 129 133 # double-report those tests. We do double-report for timeouts since 130 134 # we still want to see the text and image output. 131 if not crash:135 if not test_output.crash: 132 136 failures.extend(new_failures) 133 137 time_for_diffs[test_type.__class__.__name__] = ( … … 135 139 136 140 total_time_for_all_diffs = time.time() - start_diff_time 137 return test_results.TestResult(test_input.filename, failures, test_ run_time,141 return test_results.TestResult(test_input.filename, failures, test_output.test_time, 138 142 total_time_for_all_diffs, time_for_diffs) 139 143 … … 156 160 def _should_fetch_expected_checksum(options): 157 161 return options.pixel_tests and not (options.new_baseline or options.reset_results) 162 163 164 def _run_single_test(port, options, test_input, test_types, test_args, driver): 165 # FIXME: Pull this into TestShellThread._run(). 166 167 # The image hash is used to avoid doing an image dump if the 168 # checksums match, so it should be set to a blank value if we 169 # are generating a new baseline. (Otherwise, an image from a 170 # previous run will be copied into the baseline.""" 171 if _should_fetch_expected_checksum(options): 172 image_hash_to_driver = port.expected_checksum(test_input.filename) 173 else: 174 image_hash_to_driver = None 175 test_input.uri = port.filename_to_uri(test_input.filename).strip() 176 test_output = driver.run_test(test_input.uri, test_input.timeout, image_hash_to_driver) 177 return _process_output(port, options, test_input, test_types, test_args, 178 test_output) 158 179 159 180 … … 186 207 # FIXME: this is a separate routine to work around a bug 187 208 # in coverage: see http://bitbucket.org/ned/coveragepy/issue/85. 188 189 # FIXME: Pull this into TestShellThread._run().190 test_input = self._test_input191 test_input.uri = self._port.filename_to_uri(test_input.filename)192 if _should_fetch_expected_checksum(self._options):193 test_input.image_checksum = self._port.expected_checksum(test_input.filename)194 195 start = time.time()196 209 self._driver = self._port.create_driver(self._test_args.png_path, 197 210 self._options) 198 211 self._driver.start() 199 crash, timeout, actual_checksum, output, error = \ 200 self._driver.run_test(test_input.uri, test_input.timeout, 201 test_input.image_checksum) 202 end = time.time() 203 self._test_result = _process_output(self._port, self._options, 204 test_input, self._test_types, self._test_args, 205 crash, timeout, end - start, 206 actual_checksum, output, error) 212 self._test_result = _run_single_test(self._port, self._options, 213 self._test_input, self._test_types, 214 self._test_args, self._driver) 207 215 self._driver.stop() 208 216 … … 502 510 """ 503 511 self._ensure_dump_render_tree_is_running() 504 # The pixel_hash is used to avoid doing an image dump if the505 # checksums match, so it should be set to a blank value if we506 # are generating a new baseline. (Otherwise, an image from a507 # previous run will be copied into the baseline.)508 509 # FIXME: Pull this into TestShellThread._run().510 test_input.uri = self._port.filename_to_uri(test_input.filename)511 if _should_fetch_expected_checksum(self._options):512 test_input.image_checksum = self._port.expected_checksum(test_input.filename)513 start = time.time()514 515 512 thread_timeout = _milliseconds_to_seconds( 516 513 _pad_timeout(int(test_input.timeout))) 517 self._next_timeout = start + thread_timeout 518 519 crash, timeout, actual_checksum, output, error = \ 520 self._driver.run_test(test_input.uri, test_input.timeout, test_input.image_checksum) 521 end = time.time() 522 523 result = _process_output(self._port, self._options, 524 test_input, self._test_types, 525 self._test_args, crash, 526 timeout, end - start, actual_checksum, 527 output, error) 528 self._test_results.append(result) 529 return result 514 self._next_timeout = time.time() + thread_timeout 515 test_result = _run_single_test(self._port, self._options, test_input, 516 self._test_types, self._test_args, 517 self._driver) 518 self._test_results.append(test_result) 519 return test_result 530 520 531 521 def _ensure_dump_render_tree_is_running(self): -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/port/base.py
r71580 r72249 833 833 test 834 834 835 Returns a tuple of the following: 836 crash - a boolean indicating whether the driver crashed on the test 837 timeout - a boolean indicating whehter the test timed out 838 checksum - a string containing the checksum of the image, if 839 present 840 output - any text output 841 error - any unexpected or additional (or error) text output 842 843 Note that the image itself should be written to the path that was 844 specified in the __init__() call.""" 835 Returns a TestOutput object. 836 """ 845 837 raise NotImplementedError('Driver.run_test') 846 838 -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/port/chromium.py
r70789 r72249 47 47 from webkitpy.common.system.path import cygpath 48 48 from webkitpy.layout_tests.layout_package import test_expectations 49 from webkitpy.layout_tests.layout_package import test_output 49 50 50 51 import base 51 52 import http_server 52 53 from webkitpy.common.system.executive import Executive54 from webkitpy.layout_tests.layout_package import test_expectations55 53 56 54 # Chromium DRT on OSX uses WebKitDriver. … … 448 446 return cmd 449 447 448 def _output_image(self): 449 """Returns the image output which driver generated.""" 450 png_path = self._image_path 451 if png_path and os.path.isfile(png_path): 452 with open(png_path, 'rb') as image_file: 453 return image_file.read() 454 else: 455 return None 456 450 457 def run_test(self, uri, timeoutms, checksum): 451 458 output = [] … … 499 506 (line, crash) = self._write_command_and_read_line(input=None) 500 507 501 return (crash, timeout, actual_checksum, ''.join(output), 502 ''.join(error)) 508 return test_output.TestOutput( 509 ''.join(output), self._output_image(), actual_checksum, 510 crash, time.time() - start_time, timeout, ''.join(error)) 503 511 504 512 def stop(self): -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/port/dryrun.py
r70013 r72249 49 49 import os 50 50 import sys 51 import time 52 53 from webkitpy.layout_tests.layout_package import test_output 51 54 52 55 import base … … 110 113 111 114 def run_test(self, uri, timeoutms, image_hash): 115 start_time = time.time() 112 116 test_name = self._port.uri_to_test_name(uri) 113 117 path = os.path.join(self._port.layout_tests_dir(), test_name) … … 116 120 if image_hash is not None: 117 121 image = self._port.expected_image(path) 118 if image and self._image_path:119 with open(self._image_path, 'w') as f:120 f.write(image)121 122 hash = self._port.expected_checksum(path) 122 123 else: 124 image = None 123 125 hash = None 124 return (False, False, hash, text_output, None) 126 return test_output.TestOutput(text_output, image, hash, False, 127 time.time() - start_time, False, None) 125 128 126 129 def start(self): -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/port/test.py
r70277 r72249 36 36 import sys 37 37 import time 38 39 from webkitpy.layout_tests.layout_package import test_output 38 40 39 41 import base … … 290 292 291 293 def run_test(self, uri, timeoutms, image_hash): 294 start_time = time.time() 292 295 test_name = self._port.uri_to_test_name(uri) 293 296 test = self._port._tests[test_name] … … 298 301 if test.hang: 299 302 time.sleep((float(timeoutms) * 4) / 1000.0) 300 301 if self._port.get_option('pixel_tests') and test.actual_image: 302 with open(self._image_path, 'w') as file: 303 file.write(test.actual_image) 304 305 return (test.crash, test.timeout, test.actual_checksum, 306 test.actual_text, test.error) 303 return test_output.TestOutput(test.actual_text, test.actual_image, 304 test.actual_checksum, test.crash, 305 time.time() - start_time, test.timeout, 306 test.error) 307 307 308 308 def start(self): -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/port/webkit.py
r71580 r72249 50 50 51 51 import webkitpy.common.system.ospath as ospath 52 import webkitpy.layout_tests.layout_package.test_output as test_output 52 53 import webkitpy.layout_tests.port.base as base 53 54 import webkitpy.layout_tests.port.server_process as server_process … … 443 444 command += "\n" 444 445 446 start_time = time.time() 445 447 self._server_process.write(command) 446 448 … … 487 489 line = self._server_process.read_line(timeout) 488 490 489 if self._image_path and len(self._image_path):490 with open(self._image_path, "wb") as image_file:491 image_file.write(image)492 493 491 error_lines = self._server_process.error.splitlines() 494 492 # FIXME: This is a hack. It is unclear why sometimes … … 501 499 # this reset in. 502 500 self._server_process.error = "" 503 return (self._server_process.crashed,504 self._server_process.timed_out,505 actual_image_hash,506 output,507 error)501 return test_output.TestOutput(output, image, actual_image_hash, 502 self._server_process.crashed, 503 time.time() - start_time, 504 self._server_process.timed_out, 505 error) 508 506 509 507 def stop(self): -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/run_webkit_tests.py
r72149 r72249 102 102 # FIXME: filename should really be test_name as a relative path. 103 103 self.filename = filename 104 # The image checksum is passed to the driver so that the driver can optionally not have105 # to output the image if the checksums match.106 self.image_checksum = None107 104 self.timeout = timeout 108 105 -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/test_types/image_diff.py
r69153 r72249 55 55 class ImageDiff(test_type_base.TestTypeBase): 56 56 57 def _copy_output_png(self, test_filename, source_image, extension): 58 """Copies result files into the output directory with appropriate 59 names. 60 61 Args: 62 test_filename: the test filename 63 source_file: path to the image file (either actual or expected) 64 extension: extension to indicate -actual.png or -expected.png 65 """ 66 self._make_output_directory(test_filename) 67 dest_image = self.output_filename(test_filename, extension) 68 69 if os.path.exists(source_image): 70 shutil.copyfile(source_image, dest_image) 71 72 def _save_baseline_files(self, filename, png_path, checksum, 57 def _save_baseline_files(self, filename, image, image_hash, 73 58 generate_new_baseline): 74 59 """Saves new baselines for the PNG and checksum. … … 76 61 Args: 77 62 filename: test filename 78 png_path: path to the actual PNG result file79 checksum: value of the actual checksum result63 image: a image output 64 image_hash: a checksum of the image 80 65 generate_new_baseline: whether to generate a new, platform-specific 81 66 baseline, or update the existing one 82 67 """ 83 with open(png_path, "rb") as png_file: 84 png_data = png_file.read() 85 self._save_baseline_data(filename, png_data, ".png", encoding=None, 68 self._save_baseline_data(filename, image, ".png", encoding=None, 86 69 generate_new_baseline=generate_new_baseline) 87 self._save_baseline_data(filename, checksum, ".checksum",70 self._save_baseline_data(filename, image_hash, ".checksum", 88 71 encoding="ascii", 89 72 generate_new_baseline=generate_new_baseline) 90 73 91 def _create_image_diff(self, port, filename, configuration): 74 def _copy_image(self, filename, actual_image, expected_image): 75 self.write_output_files(filename, '.png', 76 output=actual_image, expected=expected_image, 77 encoding=None, print_text_diffs=False) 78 79 def _copy_image_hash(self, filename, actual_image_hash, expected_image_hash): 80 self.write_output_files(filename, '.checksum', 81 actual_image_hash, expected_image_hash, 82 encoding="ascii", print_text_diffs=False) 83 84 def _create_diff_image(self, port, filename, actual_image, expected_image): 92 85 """Creates the visual diff of the expected/actual PNGs. 93 86 94 Args: 95 filename: the name of the test 96 configuration: Debug or Release 97 Returns True if the files are different, False if they match 87 Returns True if the images are different. 98 88 """ 99 89 diff_filename = self.output_filename(filename, 100 self.FILENAME_SUFFIX_COMPARE) 101 actual_filename = self.output_filename(filename, 102 self.FILENAME_SUFFIX_ACTUAL + '.png') 103 expected_filename = self.output_filename(filename, 104 self.FILENAME_SUFFIX_EXPECTED + '.png') 90 self.FILENAME_SUFFIX_COMPARE) 91 return port.diff_image(actual_image, expected_image, diff_filename) 105 92 106 expected_image = port.expected_image(filename) 107 with codecs.open(actual_filename, 'r+b', None) as file: 108 actual_image = file.read() 109 110 result = port.diff_image(expected_image, actual_image, 111 diff_filename) 112 return result 113 114 def compare_output(self, port, filename, output, test_args, configuration): 93 def compare_output(self, port, filename, test_args, actual_test_output, 94 expected_test_output): 115 95 """Implementation of CompareOutput that checks the output image and 116 96 checksum against the expected files from the LayoutTest directory. … … 119 99 120 100 # If we didn't produce a hash file, this test must be text-only. 121 if test_args.hash is None:101 if actual_test_output.image_hash is None: 122 102 return failures 123 103 124 104 # If we're generating a new baseline, we pass. 125 105 if test_args.new_baseline or test_args.reset_results: 126 self._save_baseline_files(filename, test_args.png_path, 127 test_args.hash, test_args.new_baseline) 106 self._save_baseline_files(filename, actual_test_output.image_hash, 107 actual_test_output.image, 108 test_args.new_baseline) 128 109 return failures 129 110 130 # Compare hashes. 131 expected_hash = self._port.expected_checksum(filename) 132 expected_png = self._port.expected_image(filename) 133 134 if not expected_png: 111 if not expected_test_output.image: 135 112 # Report a missing expected PNG file. 136 self.write_output_files(filename, '.checksum', 137 test_args.hash, expected_hash, 138 encoding="ascii", 139 print_text_diffs=False) 140 self._copy_output_png(filename, test_args.png_path, '-actual.png') 113 self._copy_image(filename, actual_test_output.image, expected_image=None) 114 self._copy_image_hash(filename, actual_test_output.image_hash, 115 expected_test_output.image_hash) 141 116 failures.append(test_failures.FailureMissingImage()) 142 117 return failures 143 elif test_args.hash == expected_hash: 118 if not expected_test_output.image_hash: 119 # Report a missing expected checksum file. 120 self._copy_image(filename, actual_test_output.image, 121 expected_test_output.image) 122 self._copy_image_hash(filename, actual_test_output.image_hash, 123 expected_image_hash=None) 124 failures.append(test_failures.FailureMissingImageHash()) 125 return failures 126 127 if actual_test_output.image_hash == expected_test_output.image_hash: 144 128 # Hash matched (no diff needed, okay to return). 145 129 return failures 146 130 147 self.write_output_files(filename, '.checksum', 148 test_args.hash, expected_hash, 149 encoding="ascii", 150 print_text_diffs=False) 151 152 # FIXME: combine next two lines 153 self._copy_output_png(filename, test_args.png_path, '-actual.png') 154 self.write_output_files(filename, '.png', output=None, 155 expected=expected_png, 156 encoding=None, print_text_diffs=False) 131 self._copy_image(filename, actual_test_output.image, 132 expected_test_output.image) 133 self._copy_image_hash(filename, actual_test_output.image_hash, 134 expected_test_output.image_hash) 157 135 158 136 # Even though we only use the result in one codepath below but we 159 137 # still need to call CreateImageDiff for other codepaths. 160 images_are_different = self._create_image_diff(port, filename, configuration) 161 if not expected_hash: 162 failures.append(test_failures.FailureMissingImageHash()) 163 elif test_args.hash != expected_hash: 164 if images_are_different: 165 failures.append(test_failures.FailureImageHashMismatch()) 166 else: 167 failures.append(test_failures.FailureImageHashIncorrect()) 138 images_are_different = self._create_diff_image(port, filename, 139 actual_test_output.image, 140 expected_test_output.image) 141 if not images_are_different: 142 failures.append(test_failures.FailureImageHashIncorrect()) 143 else: 144 failures.append(test_failures.FailureImageHashMismatch()) 168 145 169 146 return failures -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/test_types/test_type_base.py
r69171 r72249 141 141 return os.path.splitext(output_filename)[0] + modifier 142 142 143 def compare_output(self, port, filename, output, test_args, configuration): 143 def compare_output(self, port, filename, test_args, actual_test_output, 144 expected_test_output): 144 145 """Method that compares the output from the test with the 145 146 expected value. … … 148 149 149 150 Args: 151 port: object implementing port-specific information and methods 150 152 filename: absolute filename to test file 151 output: a string containing the output of the test152 153 test_args: a TestArguments object holding optional additional 153 154 arguments 154 configuration: Debug or Release 155 actual_test_output: a TestOutput object which represents actual test 156 output 157 expected_test_output: a TestOutput object which represents a expected 158 test output 155 159 156 160 Return: -
trunk/WebKitTools/Scripts/webkitpy/layout_tests/test_types/text_diff.py
r70943 r72249 56 56 return norm + "\n" 57 57 58 def _get_normalized_expected_text(self, filename): 59 """Given the filename of the test, read the expected output from a file 60 and normalize the text. Returns a string with the expected text, or '' 61 if the expected output file was not found.""" 62 return self._port.expected_text(filename) 63 64 def compare_output(self, port, filename, output, test_args, configuration): 58 def compare_output(self, port, filename, test_args, actual_test_output, 59 expected_test_output): 65 60 """Implementation of CompareOutput that checks the output text against 66 61 the expected text from the LayoutTest directory.""" … … 77 72 78 73 # Normalize text to diff 79 output = self._get_normalized_output_text(output) 80 expected = self._get_normalized_expected_text(filename) 74 actual_text = self._get_normalized_output_text(actual_test_output.text) 75 # Assuming expected_text is already normalized. 76 expected_text = expected_test_output.text 81 77 82 78 # Write output files for new tests, too. 83 if port.compare_text( output, expected):79 if port.compare_text(actual_text, expected_text): 84 80 # Text doesn't match, write output files. 85 self.write_output_files(filename, ".txt", output,86 expected , encoding=None,81 self.write_output_files(filename, ".txt", actual_text, 82 expected_text, encoding=None, 87 83 print_text_diffs=True) 88 84 89 if expected == '':85 if expected_text == '': 90 86 failures.append(test_failures.FailureMissingResult()) 91 87 else:
Note: See TracChangeset
for help on using the changeset viewer.