Chromium Code Reviews| Index: Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer.py |
| diff --git a/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer.py b/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer.py |
| index 7200ee5fa38c5360c93448587e0ef05d860100c9..970e5e1782b82abc4a5564a9a3fd45636bb6a08b 100644 |
| --- a/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer.py |
| +++ b/Tools/Scripts/webkitpy/layout_tests/controllers/test_result_writer.py |
| @@ -26,8 +26,8 @@ |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| - |
| import logging |
| +import re |
| from webkitpy.layout_tests.models import test_failures |
| @@ -52,6 +52,7 @@ def write_test_result(filesystem, port, results_directory, test_name, driver_out |
| test_failures.FailureTestHarnessAssertion)): |
| writer.write_text_files(driver_output.text, expected_driver_output.text) |
| writer.create_text_diff_and_write_result(driver_output.text, expected_driver_output.text) |
| + writer.create_overlay_invalidation_result(driver_output.text, expected_driver_output.text) |
| elif isinstance(failure, test_failures.FailureMissingImage): |
| writer.write_image_files(driver_output.image, expected_image=None) |
| elif isinstance(failure, test_failures.FailureMissingImageHash): |
| @@ -104,6 +105,7 @@ class TestResultWriter(object): |
| FILENAME_SUFFIX_PRETTY_PATCH = "-pretty-diff.html" |
| FILENAME_SUFFIX_IMAGE_DIFF = "-diff.png" |
| FILENAME_SUFFIX_IMAGE_DIFFS_HTML = "-diffs.html" |
| + FILENAME_SUFFIX_OVERLAY = "-overlay.html" |
| def __init__(self, filesystem, port, root_output_dir, test_name): |
| self._filesystem = filesystem |
| @@ -203,6 +205,137 @@ class TestResultWriter(object): |
| pretty_patch_filename = self.output_filename(self.FILENAME_SUFFIX_PRETTY_PATCH) |
| self._write_file(pretty_patch_filename, pretty_patch) |
| + def create_overlay_invalidation_result(self, actual_text, expected_text): |
| + repaintPattern = re.compile('^\(repaint rects$') |
| + repaintMatch = repaintPattern.search(expected_text) |
| + if repaintMatch == 'None': |
| + return |
| + |
| + def make_js_rect(input_str): |
| + rect_pattern = '\(rect\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\)' |
| + ret = '[' |
| + count = 0 |
| + for m in re.finditer(rect_pattern, input_str): |
| + if count > 0: |
| + ret += ',' |
| + count += 1 |
| + |
| + ret += '[' + m.group(1) + ',' |
| + ret += m.group(2) + ',' |
| + ret += m.group(3) + ',' |
| + ret += m.group(4) + ']' |
| + return ret + ']' |
| + |
| + expected_rects = make_js_rect(expected_text) |
| + actual_rects = make_js_rect(actual_text) |
| + |
| + html = """<!DOCTYPE HTML> |
| +<html> |
| +<head> |
| +<title>%(title)s</title> |
| +<style> |
| + body { |
| + margin: 0; |
| + padding: 0; |
| + } |
| + iframe { |
| + position: absolute; |
| + top: 30px; |
| + left: 0; |
| + border: 0; |
| + z-index: -1; |
| + } |
| + canvas { |
| + z-index: 1; |
| + top: 30px; |
| + left: 0; |
| + position: absolute; |
| + } |
| + #actual { display: none; } |
| +</style> |
| +</head> |
| +<body> |
| +<span id='type'>Expected Difference</span> |
| +<div class=overlay> |
| + <canvas id='expected' width='800' height='600'></canvas> |
| + <canvas id='actual' width='800' height='600'></canvas> |
| +</div> |
| +<script> |
| +(function() { |
| + var expected_rects = %(expected_rects)s; |
| + var actual_rects = %(actual_rects)s; |
| + |
| + var path = decodeURIComponent(location.search).substr(1); |
| + var iframe = document.createElement('iframe'); |
| + iframe.width = 800; |
| + iframe.height = 600; |
| + iframe.src = path; |
| + |
| + var overlay = document.querySelector('.overlay'); |
|
esprehn
2014/02/21 02:00:59
Use an id and getElementById
dsinclair
2014/02/21 02:24:55
Done.
|
| + overlay.appendChild(iframe); |
| + |
| + for (var i = expected_rects.length - 1; i >= 0; i--) { |
| + var expected_rect = expected_rects[i]; |
| + for (var k = actual_rects.length - 1; k >= 0; k--) { |
| + var actual_rect = actual_rects[k]; |
| + if ((actual_rect[0] == expected_rect[0]) && |
| + (actual_rect[1] == expected_rect[1]) && |
| + (actual_rect[2] == expected_rect[2]) && |
| + (actual_rect[3] == expected_rect[3])) { |
| + expected_rects.splice(i, 1); |
| + actual_rects.splice(k, 1); |
| + } |
| + } |
| + } |
| + |
| + var expected_canvas = document.querySelector('#expected') |
|
esprehn
2014/02/21 02:00:59
same
dsinclair
2014/02/21 02:24:55
Done.
|
| + var expected_ctx = expected_canvas.getContext("2d"); |
| + expected_ctx.fillStyle = 'rgba(255, 0, 0, 0.25)'; |
| + expected_ctx.strokeStyle = 'rgba(0, 0, 0, 1.0)'; |
| + for (var i = 0; i < expected_rects.length; i++) { |
| + var rect = expected_rects[i]; |
| + expected_ctx.fillRect(rect[0], rect[1], rect[2], rect[3]); |
| + expected_ctx.strokeRect(rect[0] - 2, rect[1] - 2, rect[2] + 4, rect[3] + 4); |
| + } |
| + |
| + var actual_canvas = document.querySelector('#actual') |
| + var actual_ctx = actual_canvas.getContext("2d"); |
| + actual_ctx.fillStyle = 'rgba(0, 255, 0, 0.25)'; |
| + actual_ctx.strokeStyle = 'rgba(0, 0, 0, 1.0)'; |
| + for (var i = 0; i < actual_rects.length; i++) { |
| + var rect = actual_rects[i]; |
| + actual_ctx.fillRect(rect[0], rect[1], rect[2], rect[3]); |
| + actual_ctx.strokeRect(rect[0] - 2, rect[1] - 2, rect[2] + 4, rect[3] + 4); |
| + } |
| + |
| + var type = document.querySelector('#type'); |
|
esprehn
2014/02/21 02:00:59
getElementById?
dsinclair
2014/02/21 02:24:55
Done.
|
| + var expected_showing = true; |
| + var flip = function() { |
| + if (expected_showing) { |
| + type.innerText = 'Actual Difference'; |
| + expected_canvas.style.display = 'none'; |
| + actual_canvas.style.display = 'block'; |
| + } else { |
| + type.innerText = 'Expected Difference'; |
| + actual_canvas.style.display = 'none'; |
| + expected_canvas.style.display = 'block'; |
| + } |
| + expected_showing = !expected_showing |
| + setTimeout(flip, 3000); |
| + } |
| + setTimeout(flip, 3000); |
| +})(); |
| +</script> |
| +</body> |
| +</html> |
| +""" % { |
| + 'title': self._test_name, |
| + 'expected_rects': expected_rects, |
| + 'actual_rects': actual_rects, |
| + } |
| + overlay_filename = self.output_filename(self.FILENAME_SUFFIX_OVERLAY) |
| + self._write_file(overlay_filename, html) |
| + |
| def write_audio_files(self, actual_audio, expected_audio): |
| self.write_output_files('.wav', actual_audio, expected_audio) |