2011-05-02 Ojan Vafai <ojan@chromium.org>
authorojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 May 2011 16:30:44 +0000 (16:30 +0000)
committerojan@chromium.org <ojan@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 May 2011 16:30:44 +0000 (16:30 +0000)
        Reviewed by Tony Chang.

        add image toggling behavior from old-run-webkit-tests
        https://bugs.webkit.org/show_bug.cgi?id=59978

        Add a checkbox to switch between image toggling (default)
        and just showing results for expected/actual images.

        * fast/harness/resources/results-test.js:
        * fast/harness/results-expected.txt:
        * fast/harness/results.html:
2011-05-02  Ojan Vafai  <ojan@chromium.org>

        Reviewed by Tony Chang.

        add image toggling behavior from old-run-webkit-tests
        https://bugs.webkit.org/show_bug.cgi?id=59978

        Output -diffs.html files. This matches old-run-webkit-tests.
        In theory, we could use data urls in the results.html file, but
        data urls don't currently have access to local files.

        * Scripts/webkitpy/layout_tests/layout_package/test_result_writer.py:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@85610 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/harness/resources/results-test.js
LayoutTests/fast/harness/results-expected.txt
LayoutTests/fast/harness/results.html
LayoutTests/fullscreen/full-screen-zIndex.html
Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/layout_package/test_result_writer.py

index 5d78945..c67abc1 100644 (file)
@@ -1,3 +1,17 @@
+2011-05-02  Ojan Vafai  <ojan@chromium.org>
+
+        Reviewed by Tony Chang.
+
+        add image toggling behavior from old-run-webkit-tests
+        https://bugs.webkit.org/show_bug.cgi?id=59978
+
+        Add a checkbox to switch between image toggling (default)
+        and just showing results for expected/actual images.
+
+        * fast/harness/resources/results-test.js:
+        * fast/harness/results-expected.txt:
+        * fast/harness/results.html:
+
 2011-05-03  Satish Sampath  <satish@chromium.org>
 
         Unreviewed, update test expectations for chromium.
index 34c71da..c2b4f9b 100644 (file)
@@ -207,7 +207,7 @@ function runTests()
         assertTrue(visibleExpandLinks().length == 1);
         assertTrue(document.querySelectorAll('.results-row').length == 1);
         
-        document.querySelector('.unexpected-results').checked = false;
+        document.getElementById('unexpected-results').checked = false;
 
         assertTrue(visibleExpandLinks().length == 2);
         assertTrue(document.querySelectorAll('.results-row').length == 1);
@@ -218,17 +218,17 @@ function runTests()
   
     runDefaultSingleRowTest('bar-skip.html', 'TEXT', 'SKIP', true, '', '');
     runDefaultSingleRowTest('bar-flaky-fail.html', 'PASS FAIL', 'TEXT', true, 'expected actual diff ', '');
-    runDefaultSingleRowTest('bar-flaky-fail-unexpected.html', 'PASS TEXT', 'IMAGE', false, '', 'expected actual diff ');
+    runDefaultSingleRowTest('bar-flaky-fail-unexpected.html', 'PASS TEXT', 'IMAGE', false, '', 'images diff ');
     runDefaultSingleRowTest('bar-crash.html', 'TEXT', 'CRASH', false, 'stack ', '');
     runDefaultSingleRowTest('bar-audio.html', 'TEXT', 'AUDIO', false, 'expected audio actual audio ', '');
     runDefaultSingleRowTest('bar-timeout.html', 'TEXT', 'TIMEOUT', false, 'expected actual diff ', '');
-    runDefaultSingleRowTest('bar-image.html', 'TEXT', 'IMAGE', false, '', 'expected actual diff ');
-    runDefaultSingleRowTest('bar-image-plus-text.html', 'TEXT', 'IMAGE+TEXT', false, 'expected actual diff ', 'expected actual diff ');
+    runDefaultSingleRowTest('bar-image.html', 'TEXT', 'IMAGE', false, '', 'images diff ');
+    runDefaultSingleRowTest('bar-image-plus-text.html', 'TEXT', 'IMAGE+TEXT', false, 'expected actual diff ', 'images diff ');
 
     results = mockResults();
     results.tests['bar-reftest.html'] = mockExpectation('PASS', 'IMAGE');
     results.tests['bar-reftest.html'].is_reftest = true;
-    runSingleRowTest(results, false, '', 'ref html expected actual diff ');
+    runSingleRowTest(results, false, '', 'ref html images diff ');
 
     results = mockResults();
     results.tests['bar-reftest-mismatch.html'] = mockExpectation('PASS', 'IMAGE');
@@ -367,6 +367,22 @@ function runTests()
 
     runDefaultSingleRowTest('bar-flaky-crash.html', 'TEXT', 'TIMEOUT CRASH AUDIO', false, 'expected actual diff stack expected audio actual audio ', '');
 
+    results = mockResults();
+    results.tests['bar.html'] = mockExpectation('PASS', 'IMAGE');
+    runTest(results, function() {
+        assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == 'images diff ');
+
+        document.getElementById('toggle-images').checked = false;
+        // FIXME: We shouldn't need to call updateTogglingImages. Setting checked above should call it.
+        updateTogglingImages();
+        // FIXME: We get extra spaces in the DOM every time we enable/disable image toggling.
+        assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == 'expected actual  diff ');
+        
+        document.getElementById('toggle-images').checked = true;
+        updateTogglingImages();
+        assertTrue(document.querySelector('tbody td:nth-child(3)').textContent == ' images   diff ');
+    });
+
     document.body.innerHTML = '<pre>' + g_log.join('\n') + '</pre>';
 }
 
index 47dbc75..72237ff 100644 (file)
@@ -123,3 +123,6 @@ TEST-28: PASS
 TEST-28: PASS
 TEST-28: PASS
 TEST-28: PASS
+TEST-29: PASS
+TEST-29: PASS
+TEST-29: PASS
index 77be156..1810d45 100644 (file)
@@ -12,10 +12,6 @@ p {
     margin-bottom: 0.3em;
 }
 
-tbody tr:first-of-type:hover {
-    opacity: 0.7;
-}
-
 tr:not(.results-row) td {
     white-space: nowrap;
 }
@@ -54,6 +50,10 @@ label {
     height: 600px;
 }
 
+.results-row[data-expanded="false"] {
+    display: none;
+}
+
 #options {
     position: absolute;
     top: 4px;
@@ -135,6 +135,7 @@ function globalState()
             hasTextFailures: false,
             newTests: [],
             results: {},
+            shouldToggleImages: true,
             testsWithStderr: [],
             unexpectedPassTests: []
         }
@@ -166,7 +167,17 @@ function parentOfType(node, selector)
     return null;
 }
 
-function appendResultIframe(src, parent)
+function remove(node)
+{
+    node.parentNode.removeChild(node);
+}
+
+function forEach(nodeList, handler)
+{
+    Array.prototype.forEach.call(nodeList, handler);
+}
+
+function resultIframe(src)
 {
     // FIXME: use audio tags for AUDIO tests?
     var layoutTestsIndex = src.indexOf('LayoutTests');
@@ -184,10 +195,15 @@ function appendResultIframe(src, parent)
 
     var tagName = (src.lastIndexOf('.png') == -1) ? 'iframe' : 'img';
 
-    var container = document.createElement('div');
-    container.className = 'result-container';
-    container.innerHTML = '<div class=label>' + name + '</div><' + tagName + ' src="' + src + '?format=txt"></' + tagName + '>';
-    parent.appendChild(container);
+    if (tagName != 'img')
+        src += '?format=txt';
+    return '<div class=result-container><div class=label>' + name + '</div><' + tagName + ' src="' + src + '"></' + tagName + '></div>';
+}
+
+function togglingImage(prefix)
+{
+    return '<div class=result-container><div class="label imageText"></div><img class=animatedImage data-prefix="' +
+        prefix + '"></img></div>';
 }
 
 function toggleExpectations(e)
@@ -207,7 +223,13 @@ function collapseExpectations(expandLink)
     expandLink.textContent = '+';
     var existingResultsRow = parentOfType(expandLink, 'tbody').querySelector('.results-row');
     if (existingResultsRow)
-        existingResultsRow.style.display = 'none';
+        updateExpandedState(existingResultsRow, false);
+}
+
+function updateExpandedState(row, isExpanded)
+{
+    row.setAttribute('data-expanded', isExpanded);
+    updateImageTogglingTimer();
 }
 
 function expandExpectations(expandLink)
@@ -219,7 +241,7 @@ function expandExpectations(expandLink)
     var enDash = '\u2013';
     expandLink.textContent = enDash;
     if (existingResultsRow) {
-        existingResultsRow.style.display = '';
+        updateExpandedState(existingResultsRow, true);
         return;
     }
     
@@ -228,14 +250,43 @@ function expandExpectations(expandLink)
     var newCell = document.createElement('td');
     newCell.colSpan = row.querySelectorAll('td').length;
 
-    appendResultIframe(row.querySelector('.test-link').href, newCell);
+    newCell.insertAdjacentHTML('beforeEnd', resultIframe(row.querySelector('.test-link').href));    
 
     var resultLinks = row.querySelectorAll('.result-link');
-    for (var i = 0; i < resultLinks.length; i++)
-        appendResultIframe(resultLinks[i].href, newCell);
+    var hasTogglingImages = false;
+    for (var i = 0; i < resultLinks.length; i++) {
+        var link = resultLinks[i];
+        var result;
+        if (link.textContent == 'images') {
+            hasTogglingImages = true;
+            result = togglingImage(link.getAttribute('data-prefix'));
+        } else
+            result = resultIframe(link.href);
+
+        newCell.insertAdjacentHTML('beforeEnd', result);    
+    }
 
     newRow.appendChild(newCell);
     parentTbody.appendChild(newRow);
+
+    updateExpandedState(newRow, true);
+
+    updateImageTogglingTimer();
+}
+
+function updateImageTogglingTimer()
+{
+    var hasVisibleAnimatedImage = document.querySelector('.results-row[data-expanded="true"] .animatedImage');
+    if (!hasVisibleAnimatedImage) {
+        clearInterval(globalState().togglingImageInterval);
+        globalState().togglingImageInterval = null;
+        return;
+    }
+
+    if (!globalState().togglingImageInterval) {
+        toggleImages();
+        globalState().togglingImageInterval = setInterval(toggleImages, 2000);
+    }
 }
 
 function async(func, args)
@@ -286,7 +337,7 @@ function testLink(test)
 
 function resultLink(testPrefix, suffix, contents)
 {
-    return '<a class=result-link href="' + testPrefix + suffix + '">' + contents + '</a> ';
+    return '<a class=result-link href="' + testPrefix + suffix + '" data-prefix="' + testPrefix + '">' + contents + '</a> ';
 }
 
 function testObjectFor(test)
@@ -338,6 +389,23 @@ function processGlobalStateFor(testObject)
         globalState().unexpectedPassTests.push(test);            
 }
 
+function toggleImages()
+{
+    var images = document.querySelectorAll('.animatedImage');
+    var imageTexts = document.querySelectorAll('.imageText');
+    for (var i = 0, len = images.length; i < len; i++) {
+        var image = images[i];
+        var text = imageTexts[i];
+        if (text.textContent == 'Expected Image') {
+            text.textContent = 'Actual Image';
+            image.src = image.getAttribute('data-prefix') + '-actual.png';
+        } else {
+            text.textContent = 'Expected Image';
+            image.src = image.getAttribute('data-prefix') + '-expected.png';
+        }
+    }
+}
+
 function tableRow(testObject)
 {    
     var row = '<tbody'
@@ -384,10 +452,16 @@ function tableRow(testObject)
         } else {
             if (testObject.is_reftest)
                 row += resultLink(test_prefix, '-expected.html', 'ref html');
-
-            row += resultLink(test_prefix, '-expected.png', 'expected') +
-                resultLink(test_prefix, '-actual.png', 'actual') +
-                resultLink(test_prefix, '-diff.png', 'diff');
+            
+            if (globalState().shouldToggleImages) {
+                row += resultLink(test_prefix, '-diffs.html', 'images');
+            } else {
+                row += resultLink(test_prefix, '-expected.png', 'expected');
+                row += resultLink(test_prefix, '-actual.png', 'actual');
+            }
+
+            // FIXME: old-run-webkit-tests shows the diff percentage as the text contents of the "diff" link.
+            row += resultLink(test_prefix, '-diff.png', 'diff');
         }
     }
 
@@ -571,18 +645,32 @@ var PixelZoomer = {};
 
 PixelZoomer.showOnDelay = true;
 
+PixelZoomer._zoomImageContainer = function(url)
+{
+    return '<div class=zoom-image-container><img src="' + url + '"></div>';
+}
+
 PixelZoomer._createContainer = function(e)
 {
     var tbody = parentOfType(e.target, 'tbody');
-    var imageDiffLinks = tbody.querySelector('tr').querySelectorAll('a[href$=".png"]');
+    var row = tbody.querySelector('tr');
+    var imageDiffLinks = row.querySelectorAll('a[href$=".png"]');
     
     var container = document.createElement('div');
     container.className = 'pixel-zoom-container';
     
     var html = '';
-    for (var i = 0; i < imageDiffLinks.length; i++)
-        html += '<div class=zoom-image-container><img src="' + imageDiffLinks[i].href + '"></div>';
     
+    var togglingImageLink = row.querySelector('a[href$="-diffs.html"]');
+    if (togglingImageLink) {
+        var prefix = togglingImageLink.getAttribute('data-prefix');
+        html += PixelZoomer._zoomImageContainer(prefix + '-expected.png') +
+            PixelZoomer._zoomImageContainer(prefix + '-actual.png');
+    }
+    
+    for (var i = 0; i < imageDiffLinks.length; i++)
+        html += PixelZoomer._zoomImageContainer(imageDiffLinks[i].href);
+
     container.innerHTML = html;
     document.body.appendChild(container);
 
@@ -638,7 +726,7 @@ document.addEventListener('mousemove', PixelZoomer.handleMouseMove, false);
 
 function onlyShowUnexpectedFailures()
 {
-    var checkBox = document.querySelector('.unexpected-results');
+    var checkBox = document.getElementById('unexpected-results');
     return !checkBox || checkBox.checked;
 }
 
@@ -648,14 +736,65 @@ function updateExpectedFailures()
         '.expected { display: none; }' : '';
 }
 
+function updateTogglingImages()
+{
+    var shouldToggle = document.getElementById('toggle-images').checked;
+    globalState().shouldToggleImages = shouldToggle;
+    
+    if (shouldToggle) {
+        forEach(document.querySelectorAll('a[href$=".png"]'), convertToTogglingHandler(function(prefix) {
+            return resultLink(prefix, '-diffs.html', 'images');
+        }));
+        forEach(document.querySelectorAll('img[src$=".png"]'), convertToTogglingHandler(togglingImage));
+    } else {
+        forEach(document.querySelectorAll('a[href$="-diffs.html"]'), convertToNonTogglingHandler(resultLink));
+        forEach(document.querySelectorAll('.animatedImage'), convertToNonTogglingHandler(function (absolutePrefix, suffix) {
+            return resultIframe(absolutePrefix + suffix);
+        }));
+    }
+
+    updateImageTogglingTimer();
+}
+
+
+function getResultContainer(node)
+{
+    return (node.tagName == 'IMG') ? parentOfType(node, '.result-container') : node;
+}
+
+function convertToTogglingHandler(togglingImageFunction)
+{
+    return function(node) {
+        var url = (node.tagName == 'IMG') ? node.src : node.href;
+        if (url.match('-expected.png$'))
+            remove(getResultContainer(node));
+        else if (url.match('-actual.png$')) {
+            var name = parentOfType(node, 'tbody').querySelector('.test-link').textContent;
+            getResultContainer(node).outerHTML = togglingImageFunction(stripExtension(name));
+        }   
+    }
+}
+
+function convertToNonTogglingHandler(resultFunction)
+{
+    return function(node) {
+        var prefix = node.getAttribute('data-prefix');
+        getResultContainer(node).outerHTML = resultFunction(prefix, '-expected.png', 'expected') + resultFunction(prefix, '-actual.png', 'actual');
+    }
+}
+
 function generatePage()
 {
     var html = '<div id=options>' +
         '<a href="javascript:void()" class="expand-all" onclick="expandAllExpectations()">expand all</a> ' +
         '<a href="javascript:void()" class="collapse-all" onclick="collapseAllExpectations()">collapse all</a>';
 
+    // FIXME: put these options in a menu
+    // FIXME: store these as prefs in localstorage?
     if (globalState().results.uses_expectations_file)
-        html += '<label><input class="unexpected-results" type=checkbox checked onchange="updateExpectedFailures()">Only show unexpected results</label>';
+        html += '<label><input id="unexpected-results" type=checkbox checked onchange="updateExpectedFailures()">Only show unexpected results</label>';
+
+    html += '<label><input id="toggle-images" type=checkbox checked onchange="updateTogglingImages()">Toggle images</label>';
 
     html += '</div>';
 
@@ -665,7 +804,7 @@ function generatePage()
         html += '<p>Tests where results did not match expected results:</p>' +
             '<table id="results-table"><thead><tr>' +
             '<th>test</th>' +
-            '<th id="text-results-header">text results</th>' +
+            '<th id="text-results-header">results</th>' +
             '<th id="image-results-header">image results</th>' +
             '<th>failure type</th>';
 
@@ -696,8 +835,10 @@ function generatePage()
         TableSorter.sortColumn(0);
         if (!globalState().hasTextFailures)
             document.getElementById('text-results-header').textContent = '';
-        if (!globalState().hasImageFailures)
+        if (!globalState().hasImageFailures) {
             document.getElementById('image-results-header').textContent = '';
+            parentOfType(document.getElementById('toggle-images'), 'label').style.display = 'none';
+        }
     }
     
     updateExpectedFailures();
index 2d0d7ca..cffcf8e 100644 (file)
@@ -43,6 +43,6 @@
         <div>This tests that an element with a positive z-index appears behind the full screen element.  
              After entering full screen mode, only a green box should be visible.
              Click <button onclick="goFullScreen()">go full screen</button> to run the test.</div>
-        <div id="block2"></div>
-        <div id="block1"></div>
+        <div id="block2">qwer</div>
+        <div id="block1">zxcv</div>
     </body>
\ No newline at end of file
index 03acf67..f9c3f1e 100644 (file)
@@ -1,3 +1,16 @@
+2011-05-02  Ojan Vafai  <ojan@chromium.org>
+
+        Reviewed by Tony Chang.
+
+        add image toggling behavior from old-run-webkit-tests
+        https://bugs.webkit.org/show_bug.cgi?id=59978
+
+        Output -diffs.html files. This matches old-run-webkit-tests.
+        In theory, we could use data urls in the results.html file, but
+        data urls don't currently have access to local files.
+
+        * Scripts/webkitpy/layout_tests/layout_package/test_result_writer.py:
+
 2011-05-02  Tony Chang  <tony@chromium.org>
 
         Reviewed by Ojan Vafai.
index d4933bd..52ac3e9 100644 (file)
@@ -102,6 +102,7 @@ class TestResultWriter(object):
     FILENAME_SUFFIX_WDIFF = "-wdiff.html"
     FILENAME_SUFFIX_PRETTY_PATCH = "-pretty-diff.html"
     FILENAME_SUFFIX_IMAGE_DIFF = "-diff.png"
+    FILENAME_SUFFIX_IMAGE_DIFFS_HTML = "-diffs.html"
 
     def __init__(self, port, root_output_dir, filename):
         self._port = port
@@ -212,7 +213,38 @@ class TestResultWriter(object):
         # It might be better to extract 'diff' code and make it a separate function.
         # To do so, we have to change port.diff_image() as well.
         diff_filename = self.output_filename(self.FILENAME_SUFFIX_IMAGE_DIFF)
-        return self._port.diff_image(actual_image, expected_image, diff_filename)
+        images_are_different = self._port.diff_image(actual_image, expected_image, diff_filename)
+
+        if not images_are_different:
+            return False
+
+        diffs_html_filename = self.output_filename(self.FILENAME_SUFFIX_IMAGE_DIFFS_HTML)
+        # FIXME: old-run-webkit-tests shows the diff percentage as the text contents of the "diff" link.
+        # FIXME: old-run-webkit-tests include a link to the test file.
+        html = """<!DOCTYPE HTML><title>%(title)s</title>
+<style>.label{font-weight:bold}</style>
+Difference between images: <a href="%(diff_filename)s">diff</a><br>
+<div class=imageText></div><img class=animatedImage data-prefix="%(prefix)s"></img>;
+<script>
+    function toggleImages()
+    {
+        var image = document.querySelector('.animatedImage');
+        var text = document.querySelector('.imageText');
+        if (text.textContent == 'Expected Image') {
+            text.textContent = 'Actual Image';
+            image.src = image.getAttribute('data-prefix') + '-actual.png';
+        } else {
+            text.textContent = 'Expected Image';
+            image.src = image.getAttribute('data-prefix') + '-expected.png';
+        }
+    }
+    toggleImages();
+    setInterval(toggleImages, 2000)
+</script>
+""" % { 'title': self._testname, 'diff_filename': self.output_filename('-diff.png'), 'prefix': self.output_filename('') }
+        self._port._filesystem.write_binary_file(diffs_html_filename, html)
+
+        return True
 
     def copy_file(self, src_filepath, dst_extension):
         fs = self._port._filesystem