Changeset 90879 in webkit
- Timestamp:
- Jul 12, 2011 7:34:54 PM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r90876 r90879 1 2011-07-12 Adam Barth <abarth@webkit.org> 2 3 garden-o-matic should display how many times we've seen a failure 4 https://bugs.webkit.org/show_bug.cgi?id=64417 5 6 Reviewed by Ojan Vafai. 7 8 This patch adds some UI to display how many times we've seen a given 9 failure, which can be helpful for determining whether that failure is a 10 real failure or a flaky test. 11 12 When a failure has only been seen once (i.e., only a single run on a 13 single bot), we set the opacity of to 50% to avoid distracting the 14 gardener. 15 16 This patch also refactors the failure walker to have a simpler API 17 internally by moving from an object-oriented paradigm to a functional 18 paradigm. 19 20 * Scripts/webkitpy/tool/servers/data/gardeningserver/main.css: 21 * Scripts/webkitpy/tool/servers/data/gardeningserver/main.js: 22 * Scripts/webkitpy/tool/servers/data/gardeningserver/results.js: 23 * Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js: 24 * Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js: 25 * Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js: 26 1 27 2011-07-12 Chris Rogers <crogers@google.com> 2 28 -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.css
r90871 r90879 39 39 .butterbar .hide { 40 40 margin-left: 20px; 41 } 42 43 /* If we've only seen a given test failure once, we dim it so as not to distract the gardener. */ 44 .test[data-failure-count="1"] { 45 opacity: 0.5; 41 46 } 42 47 … … 125 130 color: #555; 126 131 } 132 133 .regression .when, .regression .how-many { 134 padding: 0px 2px; 135 display: inline-block; 136 } 137 138 .regression .how-many { 139 color: #555; 140 } -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/main.js
r90871 r90879 30 30 var builderNameList = base.keys(resultNodesByBuilder); 31 31 results.unifyRegressionRanges(builderNameList, testName, function(oldestFailingRevision, newestPassingRevision) { 32 $('.when', regressions).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision)); 32 $('.when', testSummary).append(ui.summarizeRegressionRange(oldestFailingRevision, newestPassingRevision)); 33 }); 34 results.countFailureOccurances(builderNameList, testName, function(failureCount) { 35 $(testSummary).attr('data-failure-count', failureCount); 36 $('.how-many', testSummary).text(ui.failureCount(failureCount)); 33 37 }); 34 38 }); -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results.js
r90871 r90879 139 139 function isUnexpectedFailure(resultNode) 140 140 { 141 if (!resultNode) 142 return false; 141 143 if (anyIsSuccess(resultNode.actual.split(' '))) 142 144 return false; … … 183 185 }; 184 186 185 function TestHistoryWalker(builderName, testName) 186 { 187 this._builderName = builderName; 188 this._testName = testName; 189 this._indexOfNextKeyToFetch = 0; 190 this._keyList = []; 191 } 192 193 TestHistoryWalker.prototype.init = function(callback) 194 { 195 var self = this; 196 197 base.jsonp(directoryOfResultsSummaryURL(self._builderName, kResultsName), function(keyList) { 198 self._keyList = keyList.map(function (element) { return element.key; }); 199 callback(); 200 }); 201 }; 202 203 TestHistoryWalker.prototype._fetchNextResultNode = function(callback) 204 { 205 var self = this; 206 207 if (self._indexOfNextKeyToFetch >= self._keyList) { 208 callback(0, null); 209 return; 187 function walkHistory(builderName, testName, callback) 188 { 189 var indexOfNextKeyToFetch = 0; 190 var keyList = []; 191 192 function continueWalk() 193 { 194 if (indexOfNextKeyToFetch >= keyList.length) { 195 processResultNode(0, null); 196 return; 197 } 198 199 var key = keyList[indexOfNextKeyToFetch]; 200 ++indexOfNextKeyToFetch; 201 g_resultsCache.get(key, function(resultsTree) { 202 var resultNode = results.resultNodeForTest(resultsTree, testName); 203 var revision = parseInt(resultsTree['revision']) 204 if (isNaN(revision)) 205 revision = 0; 206 processResultNode(revision, resultNode); 207 }); 210 208 } 211 209 212 var key = self._keyList[self._indexOfNextKeyToFetch]; 213 ++self._indexOfNextKeyToFetch; 214 g_resultsCache.get(key, function(resultsTree) { 215 var resultNode = results.resultNodeForTest(resultsTree, self._testName); 216 var revision = parseInt(resultsTree['revision']) 217 if (isNaN(revision)) 218 revision = 0; 219 callback(revision, resultNode); 220 }); 221 }; 222 223 TestHistoryWalker.prototype.walkHistory = function(callback) 224 { 225 var self = this; 226 self._fetchNextResultNode(function(revision, resultNode) { 210 function processResultNode(revision, resultNode) 211 { 227 212 var shouldContinue = callback(revision, resultNode); 228 213 if (!shouldContinue) 229 214 return; 230 self.walkHistory(callback); 215 continueWalk(); 216 } 217 218 base.jsonp(directoryOfResultsSummaryURL(builderName, kResultsName), function(directory) { 219 keyList = directory.map(function (element) { return element.key; }); 220 continueWalk(); 231 221 }); 232 222 } … … 237 227 var newestPassingRevision = 0; 238 228 239 var historyWalker = new TestHistoryWalker(builderName, testName); 240 historyWalker.init(function() { 241 historyWalker.walkHistory(function(revision, resultNode) { 242 if (!resultNode) { 243 newestPassingRevision = revision; 244 callback(oldestFailingRevision, newestPassingRevision); 245 return false; 246 } 247 if (isUnexpectedFailure(resultNode)) { 248 oldestFailingRevision = revision; 249 return true; 250 } 251 if (!oldestFailingRevision) 252 return true; // We need to keep looking for a failing revision. 229 walkHistory(builderName, testName, function(revision, resultNode) { 230 if (!resultNode) { 253 231 newestPassingRevision = revision; 254 232 callback(oldestFailingRevision, newestPassingRevision); 255 233 return false; 256 }); 234 } 235 if (isUnexpectedFailure(resultNode)) { 236 oldestFailingRevision = revision; 237 return true; 238 } 239 if (!oldestFailingRevision) 240 return true; // We need to keep looking for a failing revision. 241 newestPassingRevision = revision; 242 callback(oldestFailingRevision, newestPassingRevision); 243 return false; 257 244 }); 258 245 }; … … 298 285 callback(mergedRange.oldestFailingRevision, mergedRange.newestPassingRevision); 299 286 } 287 }); 288 }); 289 }; 290 291 results.countFailureOccurances = function(builderNameList, testName, callback) 292 { 293 var queriesInFlight = builderNameList.length; 294 if (!queriesInFlight) 295 callback(0); 296 297 var failureCount = 0; 298 $.each(builderNameList, function(index, builderName) { 299 walkHistory(builderName, testName, function(revision, resultNode) { 300 if (isUnexpectedFailure(resultNode)) { 301 ++failureCount; 302 return true; 303 } 304 305 --queriesInFlight; 306 if (!queriesInFlight) 307 callback(failureCount); 308 return false; 300 309 }); 301 310 }); -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/results_unittests.js
r90866 r90879 138 138 } 139 139 140 test(" regressionRangeForFailure", 5, function() {140 test("walkHistory", 6, function() { 141 141 var simulator = new NetworkSimulator(); 142 142 … … 246 246 equals(newestPassingRevision, 90425); 247 247 }); 248 249 results.countFailureOccurances(["Mock Builder", "Another Builder"], "userscripts/another-test.html", function(failureCount) { 250 equals(failureCount, 4); 251 }); 248 252 }); 249 253 }); -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui.js
r90871 r90879 34 34 '<ul class="where"></ul>' + 35 35 '<div class="when"></div>' + 36 '<div class="how-many"></div>' + 36 37 '</div>'); 37 38 $('.what a', block).text(testName).attr('href', ui.urlForTest(testName)).attr('class', unexpectedResults.join(' ')); … … 62 63 }; 63 64 65 ui.failureCount = function(failureCount) 66 { 67 if (failureCount < 1) 68 return ''; 69 if (failureCount == 1) 70 return '(Seen once.)'; 71 return '(Seen ' + failureCount + ' times.)'; 72 }; 73 64 74 ui.results = function(resultsURLs) 65 75 { -
trunk/Tools/Scripts/webkitpy/tool/servers/data/gardeningserver/ui_unittests.js
r90871 r90879 39 39 }); 40 40 41 test("failureCount", 4, function() { 42 equal(ui.failureCount(0), ''); 43 equal(ui.failureCount(1), '(Seen once.)'); 44 equal(ui.failureCount(2), '(Seen 2 times.)'); 45 equal(ui.failureCount(3), '(Seen 3 times.)'); 46 }); 47 41 48 test("results", 1, function() { 42 49 var testResults = ui.results([
Note: See TracChangeset
for help on using the changeset viewer.