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..ac180cce668f11008fcce08fc1f4b8ef2374f4b3 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,133 @@ 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): |
Dirk Pranke
2014/02/27 20:57:44
Can you pull this whole function out of this file
|
+ repaintPattern = re.compile('^\(repaint rects$') |
+ repaintMatch = repaintPattern.search(expected_text) |
Dirk Pranke
2014/02/27 20:57:44
this can probably be just re.search('^\(repaint re
|
+ 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): |
Dirk Pranke
2014/02/27 20:57:44
hm. didn't know about finditer(); nifty.
|
+ if count > 0: |
+ ret += ',' |
+ count += 1 |
+ |
+ ret += '[' + m.group(1) + ',' |
+ ret += m.group(2) + ',' |
+ ret += m.group(3) + ',' |
+ ret += m.group(4) + ']' |
+ return ret + ']' |
Dirk Pranke
2014/02/27 20:57:44
hm. didn't know about finditer(); nifty.
This can
|
+ |
+ expected_rects = make_js_rect(expected_text) |
+ actual_rects = make_js_rect(actual_text) |
+ |
+ html = """<!DOCTYPE HTML> |
Dirk Pranke
2014/02/27 20:57:44
I defer to ojan re: the html template, but it look
|
+<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 id=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.getElementById('overlay'); |
+ 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.getElementById('expected'); |
+ var expected_ctx = expected_canvas.getContext("2d"); |
+ expected_ctx.fillStyle = 'rgba(255, 0, 0, 0.25)'; |
+ 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]); |
+ } |
+ |
+ var actual_canvas = document.getElementById('actual'); |
+ var actual_ctx = actual_canvas.getContext("2d"); |
+ actual_ctx.fillStyle = 'rgba(0, 255, 0, 0.25)'; |
+ 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]); |
+ } |
+ |
+ var type = document.getElementById('type'); |
+ var expected_showing = true; |
+ var flip = function() { |
+ if (expected_showing) { |
+ type.innerText = 'Actual Difference'; |
ojan
2014/02/25 00:43:42
Nit: innerText is crazy. Use textContent.
|
+ 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) |