Title: [90879] trunk/Tools
Revision
90879
Author
[email protected]
Date
2011-07-12 19:34:54 -0700 (Tue, 12 Jul 2011)

Log Message

garden-o-matic should display how many times we've seen a failure
https://bugs.webkit.org/show_bug.cgi?id=64417

Reviewed by Ojan Vafai.

This patch adds some UI to display how many times we've seen a given
failure, which can be helpful for determining whether that failure is a
real failure or a flaky test.

When a failure has only been seen once (i.e., only a single run on a
single bot), we set the opacity of to 50% to avoid distracting the
gardener.

This patch also refactors the failure walker to have a simpler API
internally by moving from an object-oriented paradigm to a functional
paradigm.

* Scripts/webkitpy/tool/servers/data/gardeningserver/main.css:
* Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/results.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
* Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (90878 => 90879)


--- trunk/Tools/ChangeLog	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/ChangeLog	2011-07-13 02:34:54 UTC (rev 90879)
@@ -1,3 +1,29 @@
+2011-07-12  Adam Barth  <[email protected]>
+
+        garden-o-matic should display how many times we've seen a failure
+        https://bugs.webkit.org/show_bug.cgi?id=64417
+
+        Reviewed by Ojan Vafai.
+
+        This patch adds some UI to display how many times we've seen a given
+        failure, which can be helpful for determining whether that failure is a
+        real failure or a flaky test.
+
+        When a failure has only been seen once (i.e., only a single run on a
+        single bot), we set the opacity of to 50% to avoid distracting the
+        gardener.
+
+        This patch also refactors the failure walker to have a simpler API
+        internally by moving from an object-oriented paradigm to a functional
+        paradigm.
+
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.css:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/main.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/results.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js:
+        * Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js:
+
 2011-07-12  Chris Rogers  <[email protected]>
 
         Enable Web Audio for chromium DRT

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css	2011-07-13 02:34:54 UTC (rev 90879)
@@ -40,6 +40,11 @@
     margin-left: 20px;
 }
 
+/* If we've only seen a given test failure once, we dim it so as not to distract the gardener. */
+.test[data-failure-count="1"] {
+    opacity: 0.5;
+}
+
 .regression {
     padding: 0 0 10px 0;
 }
@@ -124,3 +129,12 @@
     border-radius: 4px;
     color: #555;
 }
+
+.regression .when, .regression .how-many {
+    padding: 0px 2px;
+    display: inline-block;
+}
+
+.regression .how-many {
+    color: #555;
+}

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js	2011-07-13 02:34:54 UTC (rev 90879)
@@ -29,8 +29,12 @@
 
                 var builderNameList = base.keys(resultNodesByBuilder);
                 results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) {
-                    $('.when', regressions).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
+                    $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision));
                 });
+                results.countFailureOccurances(builderNameList, testName, function(failureCount) {
+                    $(testSummary).attr('data-failure-count', failureCount);
+                    $('.how-many', testSummary).text(ui.failureCount(failureCount));
+                });
             });
             $('.results').append(regressions);
         }

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js	2011-07-13 02:34:54 UTC (rev 90879)
@@ -138,6 +138,8 @@
 
 function isUnexpectedFailure(resultNode)
 {
+    if (!resultNode)
+        return false;
     if (anyIsSuccess(resultNode.actual.split(' ')))
         return false;
     return anyIsFailure(unexpectedResults(resultNode));
@@ -182,52 +184,40 @@
     return base.uniquifyArray(results);
 };
 
-function TestHistoryWalker(builderName, testName)
+function walkHistory(builderName, testName, callback)
 {
-    this._builderName = builderName;
-    this._testName = testName;
-    this._indexOfNextKeyToFetch = 0;
-    this._keyList = [];
-}
+    var indexOfNextKeyToFetch = 0;
+    var keyList = [];
 
-TestHistoryWalker.prototype.init = function(callback)
-{
-    var self = this;
+    function continueWalk()
+    {
+        if (indexOfNextKeyToFetch >= keyList.length) {
+            processResultNode(0, null);
+            return;
+        }
 
-    base.jsonp(directoryOfResultsSummaryURL(self._builderName, kResultsName), function(keyList) {
-        self._keyList = keyList.map(function (element) { return element.key; });
-        callback();
-    });
-};
-
-TestHistoryWalker.prototype._fetchNextResultNode = function(callback)
-{
-    var self = this;
-
-    if (self._indexOfNextKeyToFetch >= self._keyList) {
-        callback(0, null);
-        return;
+        var key = keyList[indexOfNextKeyToFetch];
+        ++indexOfNextKeyToFetch;
+        g_resultsCache.get(key, function(resultsTree) {
+            var resultNode = results.resultNodeForTest(resultsTree, testName);
+            var revision = parseInt(resultsTree['revision'])
+            if (isNaN(revision))
+                revision = 0;
+            processResultNode(revision, resultNode);
+        });
     }
 
-    var key = self._keyList[self._indexOfNextKeyToFetch];
-    ++self._indexOfNextKeyToFetch;
-    g_resultsCache.get(key, function(resultsTree) {
-        var resultNode = results.resultNodeForTest(resultsTree, self._testName);
-        var revision = parseInt(resultsTree['revision'])
-        if (isNaN(revision))
-            revision = 0;
-        callback(revision, resultNode);
-    });
-};
-
-TestHistoryWalker.prototype.walkHistory = function(callback)
-{
-    var self = this;
-    self._fetchNextResultNode(function(revision, resultNode) {
+    function processResultNode(revision, resultNode)
+    {
         var shouldContinue = callback(revision, resultNode);
         if (!shouldContinue)
             return;
-        self.walkHistory(callback);
+        continueWalk();
+    }
+
+    base.jsonp(directoryOfResultsSummaryURL(builderName, kResultsName), function(directory) {
+        keyList = directory.map(function (element) { return element.key; });
+        continueWalk();
     });
 }
 
@@ -236,24 +226,21 @@
     var oldestFailingRevision = 0;
     var newestPassingRevision = 0;
 
-    var historyWalker = new TestHistoryWalker(builderName, testName);
-    historyWalker.init(function() {
-        historyWalker.walkHistory(function(revision, resultNode) {
-            if (!resultNode) {
-                newestPassingRevision = revision;
-                callback(oldestFailingRevision, newestPassingRevision);
-                return false;
-            }
-            if (isUnexpectedFailure(resultNode)) {
-                oldestFailingRevision = revision;
-                return true;
-            }
-            if (!oldestFailingRevision)
-                return true;  // We need to keep looking for a failing revision.
+    walkHistory(builderName, testName, function(revision, resultNode) {
+        if (!resultNode) {
             newestPassingRevision = revision;
             callback(oldestFailingRevision, newestPassingRevision);
             return false;
-        });
+        }
+        if (isUnexpectedFailure(resultNode)) {
+            oldestFailingRevision = revision;
+            return true;
+        }
+        if (!oldestFailingRevision)
+            return true;  // We need to keep looking for a failing revision.
+        newestPassingRevision = revision;
+        callback(oldestFailingRevision, newestPassingRevision);
+        return false;
     });
 };
 
@@ -301,6 +288,28 @@
     });
 };
 
+results.countFailureOccurances = function(builderNameList, testName, callback)
+{
+    var queriesInFlight = builderNameList.length;
+    if (!queriesInFlight)
+        callback(0);
+
+    var failureCount = 0;
+    $.each(builderNameList, function(index, builderName) {
+        walkHistory(builderName, testName, function(revision, resultNode) {
+            if (isUnexpectedFailure(resultNode)) {
+                ++failureCount;
+                return true;
+            }
+
+            --queriesInFlight;
+            if (!queriesInFlight)
+                callback(failureCount);
+            return false;
+        });
+    });
+};
+
 results.resultNodeForTest = function(resultsTree, testName)
 {
     var testNamePath = testName.split('/');

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js	2011-07-13 02:34:54 UTC (rev 90879)
@@ -137,7 +137,7 @@
     equal(window.base, realBase, "Failed to restore real base!");
 }
 
-test("regressionRangeForFailure", 5, function() {
+test("walkHistory", 6, function() {
     var simulator = new NetworkSimulator();
 
     var keyMap = {
@@ -245,6 +245,10 @@
             equals(oldestFailingRevision, 90426);
             equals(newestPassingRevision, 90425);
         });
+
+        results.countFailureOccurances(["Mock Builder", "Another Builder"], "userscripts/another-test.html", function(failureCount) {
+            equals(failureCount, 4);
+        });
     });
 });
 

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js	2011-07-13 02:34:54 UTC (rev 90879)
@@ -33,6 +33,7 @@
           '<span>fails on</span>' +
           '<ul class="where"></ul>' +
           '<div class="when"></div>' +
+          '<div class="how-many"></div>' +
         '</div>');
     $('.what a', block).text(testName).attr('href', ui.urlForTest(testName)).attr('class', unexpectedResults.join(' '));
 
@@ -61,6 +62,15 @@
     return block;
 };
 
+ui.failureCount = function(failureCount)
+{
+    if (failureCount < 1)
+        return '';
+    if (failureCount == 1)
+        return '(Seen once.)';
+    return '(Seen ' + failureCount + ' times.)';
+};
+
 ui.results = function(resultsURLs)
 {
     var block = $('<div class="results"></div>');

Modified: trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js (90878 => 90879)


--- trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js	2011-07-13 02:28:17 UTC (rev 90878)
+++ trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js	2011-07-13 02:34:54 UTC (rev 90879)
@@ -38,6 +38,13 @@
     equal(summaryWithOneRevision.parent().html(), '<div class="regression-range">Regression Range: <a href=""
 });
 
+test("failureCount", 4, function() {
+    equal(ui.failureCount(0), '');
+    equal(ui.failureCount(1), '(Seen once.)');
+    equal(ui.failureCount(2), '(Seen 2 times.)');
+    equal(ui.failureCount(3), '(Seen 3 times.)');
+});
+
 test("results", 1, function() {
     var testResults = ui.results([
         'http://example.com/layout-test-results/foo-bar-expected.txt',
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to