summaryrefslogtreecommitdiffstats
path: root/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py')
-rw-r--r--Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py114
1 files changed, 92 insertions, 22 deletions
diff --git a/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py b/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py
index d755f67..a8c716f 100644
--- a/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py
+++ b/Tools/Scripts/webkitpy/layout_tests/layout_package/single_test_runner.py
@@ -44,14 +44,6 @@ def run_single_test(port, options, test_input, driver, worker_name):
return runner.run()
-class ExpectedDriverOutput:
- """Groups information about an expected driver output."""
- def __init__(self, text, image, image_hash):
- self.text = text
- self.image = image
- self.image_hash = image_hash
-
-
class SingleTestRunner:
def __init__(self, options, port, driver, test_input, worker_name):
@@ -63,10 +55,43 @@ class SingleTestRunner:
self._worker_name = worker_name
self._testname = port.relative_test_filename(test_input.filename)
+ self._is_reftest = False
+ self._is_mismatch_reftest = False
+ self._reference_filename = None
+
+ fs = port._filesystem
+ reftest_expected_filename = port.reftest_expected_filename(self._filename)
+ if fs.exists(reftest_expected_filename):
+ self._is_reftest = True
+ self._reference_filename = reftest_expected_filename
+
+ reftest_expected_mismatch_filename = port.reftest_expected_mismatch_filename(self._filename)
+ if fs.exists(reftest_expected_mismatch_filename):
+ if self._is_reftest:
+ _log.error('It is not allowed that one test file has both'
+ ' expected.html file and expected-mismatch.html file'
+ ' at the same time. Please remove either %s or %s.',
+ reftest_expected_filename, reftest_expected_mismatch_filename)
+ else:
+ self._is_reftest = True
+ self._is_mismatch_reftest = True
+ self._reference_filename = reftest_expected_mismatch_filename
+
+ if self._is_reftest:
+ # Detect and report a test which has a wrong combination of expectation files.
+ # For example, if 'foo.html' has two expectation files, 'foo-expected.html' and
+ # 'foo-expected.txt', we should warn users. One test file must be used exclusively
+ # in either layout tests or reftests, but not in both.
+ for suffix in ['.txt', '.checksum', '.png']:
+ expected_filename = self._port.expected_filename(self._filename, suffix)
+ if fs.exists(expected_filename):
+ _log.error('The reftest (%s) can not have an expectation file (%s).'
+ ' Please remove that file.', self._testname, expected_filename)
+
def _expected_driver_output(self):
- return ExpectedDriverOutput(self._port.expected_text(self._filename),
- self._port.expected_image(self._filename),
- self._port.expected_checksum(self._filename))
+ return base.DriverOutput(self._port.expected_text(self._filename),
+ self._port.expected_image(self._filename),
+ self._port.expected_checksum(self._filename))
def _should_fetch_expected_checksum(self):
return (self._options.pixel_tests and
@@ -84,7 +109,13 @@ class SingleTestRunner:
def run(self):
if self._options.new_baseline or self._options.reset_results:
- return self._run_rebaseline()
+ if self._is_reftest:
+ # Returns a dummy TestResult. We don't have to rebase for reftests.
+ return TestResult(self._filename)
+ else:
+ return self._run_rebaseline()
+ if self._is_reftest:
+ return self._run_reftest()
return self._run_compare_test()
def _run_compare_test(self):
@@ -98,6 +129,8 @@ class SingleTestRunner:
def _run_rebaseline(self):
driver_output = self._driver.run_test(self._driver_input())
failures = self._handle_error(driver_output)
+ test_result_writer.write_test_result(self._port, self._options.results_directory, self._filename,
+ driver_output, None, failures)
# FIXME: It the test crashed or timed out, it might be bettter to avoid
# to write new baselines.
self._save_baselines(driver_output)
@@ -145,22 +178,31 @@ class SingleTestRunner:
port.update_baseline(output_path, data)
- def _handle_error(self, driver_output):
+ def _handle_error(self, driver_output, reference_filename=None):
+ """Returns test failures if some unusual errors happen in driver's run.
+
+ Args:
+ driver_output: The output from the driver.
+ reference_filename: The full path to the reference file which produced the driver_output.
+ This arg is optional and should be used only in reftests until we have a better way to know
+ which html file is used for producing the driver_output.
+ """
failures = []
fs = self._port._filesystem
if driver_output.timeout:
- failures.append(test_failures.FailureTimeout())
+ failures.append(test_failures.FailureTimeout(reference_filename))
+
+ if reference_filename:
+ testname = self._port.relative_test_filename(reference_filename)
+ else:
+ testname = self._testname
+
if driver_output.crash:
- failures.append(test_failures.FailureCrash())
- _log.debug("%s Stacktrace for %s:\n%s" % (self._worker_name, self._testname,
+ failures.append(test_failures.FailureCrash(reference_filename))
+ _log.debug("%s Stacktrace for %s:\n%s" % (self._worker_name, testname,
driver_output.error))
- # FIXME: Use test_result_writer module.
- stack_filename = fs.join(self._options.results_directory, self._testname)
- stack_filename = fs.splitext(stack_filename)[0] + "-stack.txt"
- fs.maybe_make_directory(fs.dirname(stack_filename))
- fs.write_text_file(stack_filename, driver_output.error)
elif driver_output.error:
- _log.debug("%s %s output stderr lines:\n%s" % (self._worker_name, self._testname,
+ _log.debug("%s %s output stderr lines:\n%s" % (self._worker_name, testname,
driver_output.error))
return failures
@@ -210,3 +252,31 @@ class SingleTestRunner:
elif driver_output.image_hash != expected_driver_outputs.image_hash:
failures.append(test_failures.FailureImageHashMismatch())
return failures
+
+ def _run_reftest(self):
+ driver_output1 = self._driver.run_test(self._driver_input())
+ driver_output2 = self._driver.run_test(
+ base.DriverInput(self._reference_filename, self._timeout, driver_output1.image_hash))
+ test_result = self._compare_output_with_reference(driver_output1, driver_output2)
+
+ test_result_writer.write_test_result(self._port, self._options.results_directory, self._filename,
+ driver_output1, driver_output2, test_result.failures)
+ return test_result
+
+ def _compare_output_with_reference(self, driver_output1, driver_output2):
+ total_test_time = driver_output1.test_time + driver_output2.test_time
+ failures = []
+ failures.extend(self._handle_error(driver_output1))
+ if failures:
+ # Don't continue any more if we already have crash or timeout.
+ return TestResult(self._filename, failures, total_test_time)
+ failures.extend(self._handle_error(driver_output2, reference_filename=self._reference_filename))
+ if failures:
+ return TestResult(self._filename, failures, total_test_time)
+
+ if self._is_mismatch_reftest:
+ if driver_output1.image_hash == driver_output2.image_hash:
+ failures.append(test_failures.FailureReftestMismatchDidNotOccur())
+ elif driver_output1.image_hash != driver_output2.image_hash:
+ failures.append(test_failures.FailureReftestMismatch())
+ return TestResult(self._filename, failures, total_test_time)