Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js

Issue 13712005: Move GardeningServer out of BuildSlaveSupport (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 var controllers = controllers || {};
27
28 (function(){
29
30 var kCheckoutUnavailableMessage = 'Failed! Garden-o-matic needs a local server t o modify your working copy. Please run "webkit-patch garden-o-matic" start the l ocal server.';
31
32 // FIXME: Where should this function go?
33 function rebaselineWithStatusUpdates(failureInfoList, resultsByTest)
34 {
35 var statusView = new ui.StatusArea('Rebaseline');
36 var id = statusView.newId();
37
38 var failuresToRebaseline = [];
39 var testNamesLogged = [];
40 failureInfoList.forEach(function(failureInfo) {
41 if (isAnyReftest(failureInfo.testName, resultsByTest)) {
42 if (testNamesLogged.indexOf(failureInfo.testName) == -1) {
43 statusView.addMessage(id, failureInfo.testName + ' is a ref test , skipping');
44 testNamesLogged.push(failureInfo.testName);
45 }
46 } else {
47 failuresToRebaseline.push(failureInfo);
48 if (testNamesLogged.indexOf(failureInfo.testName) == -1) {
49 statusView.addMessage(id, 'Rebaselining ' + failureInfo.testName + '...');
50 testNamesLogged.push(failureInfo.testName);
51 }
52 }
53 });
54
55 if (failuresToRebaseline.length) {
56 checkout.rebaseline(failuresToRebaseline, function() {
57 statusView.addFinalMessage(id, 'Rebaseline done! Please land with "w ebkit-patch land-cowhand".');
58 }, function(failureInfo) {
59 statusView.addMessage(id, failureInfo.testName + ' on ' + ui.display NameForBuilder(failureInfo.builderName));
60 }, function() {
61 statusView.addFinalMessage(id, kCheckoutUnavailableMessage);
62 });
63 } else {
64 statusView.addFinalMessage(id, 'No non-reftests left to rebaseline!')
65 }
66 }
67
68 // FIXME: This is duplicated from ui/results.js :(.
69 function isAnyReftest(testName, resultsByTest)
70 {
71 return Object.keys(resultsByTest[testName]).map(function(builder) {
72 return resultsByTest[testName][builder];
73 }).some(function(resultNode) {
74 return resultNode.reftest_type && resultNode.reftest_type.length;
75 });
76 }
77
78 // FIXME: Where should this function go?
79 function updateExpectationsWithStatusUpdates(failureInfoList)
80 {
81 var statusView = new ui.StatusArea('Expectations Update');
82 var id = statusView.newId();
83
84 var testNames = base.uniquifyArray(failureInfoList.map(function(failureInfo) { return failureInfo.testName; }));
85 var testName = testNames.length == 1 ? testNames[0] : testNames.length + ' t ests';
86 statusView.addMessage(id, 'Updating expectations of ' + testName + '...');
87
88 checkout.updateExpectations(failureInfoList, function() {
89 statusView.addFinalMessage(id, 'Expectations update done! Please land wi th "webkit-patch land-cowhand".');
90 }, function() {
91 statusView.addFinalMessage(id, kCheckoutUnavailableMessage);
92 });
93 }
94
95 controllers.ResultsDetails = base.extends(Object, {
96 init: function(view, resultsByTest)
97 {
98 this._view = view;
99 this._resultsByTest = resultsByTest;
100 this._view.setResultsByTest(resultsByTest);
101
102 this._view.firstResult();
103
104 $(this._view).bind('next', this.onNext.bind(this));
105 $(this._view).bind('previous', this.onPrevious.bind(this));
106 $(this._view).bind('rebaseline', this.onRebaseline.bind(this));
107 $(this._view).bind('expectfailure', this.onUpdateExpectations.bind(this) );
108 },
109 onNext: function()
110 {
111 this._view.nextResult();
112 },
113 onPrevious: function()
114 {
115 this._view.previousResult();
116 },
117 _failureInfoList: function()
118 {
119 var testName = this._view.currentTestName();
120 return Object.keys(this._resultsByTest[testName]).map(function(builderNa me) {
121 return results.failureInfoForTestAndBuilder(this._resultsByTest, tes tName, builderName);
122 }.bind(this));
123 },
124 onRebaseline: function()
125 {
126 rebaselineWithStatusUpdates(this._failureInfoList(), this._resultsByTest );
127 this._view.nextTest();
128 },
129 onUpdateExpectations: function()
130 {
131 updateExpectationsWithStatusUpdates(this._failureInfoList());
132 }
133 });
134
135 controllers.ExpectedFailures = base.extends(Object, {
136 init: function(model, view, delegate)
137 {
138 this._model = model;
139 this._view = view;
140 this._delegate = delegate;
141 },
142 update: function()
143 {
144 var expectedFailures = results.expectedFailuresByTest(this._model.result sByBuilder);
145 var failingTestsList = Object.keys(expectedFailures);
146
147 $(this._view).empty();
148 base.forEachDirectory(failingTestsList, function(label, testsFailingInDi rectory) {
149 var listItem = new ui.failures.ListItem(label, testsFailingInDirecto ry);
150 this._view.appendChild(listItem);
151 $(listItem).bind('examine', function() {
152 this.onExamine(testsFailingInDirectory);
153 }.bind(this));
154 }.bind(this));
155 },
156 onExamine: function(failingTestsList)
157 {
158 var resultsView = new ui.results.View({
159 fetchResultsURLs: results.fetchResultsURLs
160 });
161 var failuresByTest = base.filterDictionary(
162 results.expectedFailuresByTest(this._model.resultsByBuilder),
163 function(key) {
164 return failingTestsList.indexOf(key) != -1;
165 });
166 var controller = new controllers.ResultsDetails(resultsView, failuresByT est);
167 this._delegate.showResults(resultsView);
168 }
169 });
170
171 var FailureStreamController = base.extends(Object, {
172 _resultsFilter: null,
173 _keyFor: function(failureAnalysis) { throw "Not implemented!"; },
174 _createFailureView: function(failureAnalysis) { throw "Not implemented!"; },
175
176 init: function(model, view, delegate)
177 {
178 this._model = model;
179 this._view = view;
180 this._delegate = delegate;
181 this._testFailures = new base.UpdateTracker();
182 },
183 update: function(failureAnalysis)
184 {
185 var key = this._keyFor(failureAnalysis);
186 var failure = this._testFailures.get(key);
187 if (!failure) {
188 failure = this._createFailureView(failureAnalysis);
189 this._view.add(failure);
190 $(failure).bind('examine', function() {
191 this.onExamine(failure);
192 }.bind(this));
193 $(failure).bind('rebaseline', function() {
194 this.onRebaseline(failure);
195 }.bind(this));
196 $(failure).bind('expectfailure', function() {
197 this.onUpdateExpectations(failure);
198 }.bind(this));
199 }
200 failure.addFailureAnalysis(failureAnalysis);
201 this._testFailures.update(key, failure);
202 return failure;
203 },
204 purge: function() {
205 this._testFailures.purge(function(failure) {
206 failure.dismiss();
207 });
208 this._testFailures.forEach(function(failure) {
209 failure.purge();
210 });
211 },
212 onExamine: function(failures)
213 {
214 var resultsView = new ui.results.View({
215 fetchResultsURLs: results.fetchResultsURLs
216 });
217
218 var testNameList = failures.testNameList();
219 var failuresByTest = base.filterDictionary(
220 this._resultsFilter(this._model.resultsByBuilder),
221 function(key) {
222 return testNameList.indexOf(key) != -1;
223 });
224
225 var controller = new controllers.ResultsDetails(resultsView, failuresByT est);
226 this._delegate.showResults(resultsView);
227 },
228 _toFailureInfoList: function(failures)
229 {
230 return base.flattenArray(failures.testNameList().map(model.unexpectedFai lureInfoForTestName));
231 },
232 onRebaseline: function(failures)
233 {
234 var testNameList = failures.testNameList();
235 var failuresByTest = base.filterDictionary(
236 this._resultsFilter(this._model.resultsByBuilder),
237 function(key) {
238 return testNameList.indexOf(key) != -1;
239 });
240
241 rebaselineWithStatusUpdates(this._toFailureInfoList(failures), failuresB yTest);
242 },
243 onUpdateExpectations: function(failures)
244 {
245 updateExpectationsWithStatusUpdates(this._toFailureInfoList(failures));
246 }
247 });
248
249 controllers.UnexpectedFailures = base.extends(FailureStreamController, {
250 _resultsFilter: results.unexpectedFailuresByTest,
251
252 _impliedFirstFailingRevision: function(failureAnalysis)
253 {
254 return failureAnalysis.newestPassingRevision + 1;
255 },
256 _keyFor: function(failureAnalysis)
257 {
258 return failureAnalysis.newestPassingRevision + "+" + failureAnalysis.old estFailingRevision;
259 },
260 _createFailureView: function(failureAnalysis)
261 {
262 var failure = new ui.notifications.FailingTestsSummary();
263 model.commitDataListForRevisionRange(this._impliedFirstFailingRevision(f ailureAnalysis), failureAnalysis.oldestFailingRevision).forEach(function(commitD ata) {
264 var suspiciousCommit = failure.addCommitData(commitData);
265 $(suspiciousCommit).bind('rollout', function() {
266 this.onRollout(commitData.revision, failure.testNameList());
267 }.bind(this));
268 $(failure).bind('blame', function() {
269 this.onBlame(failure, commitData);
270 }.bind(this));
271 }, this);
272
273 return failure;
274 },
275 update: function(failureAnalysis)
276 {
277 var failure = FailureStreamController.prototype.update.call(this, failur eAnalysis);
278 failure.updateBuilderResults(model.buildersInFlightForRevision(this._imp liedFirstFailingRevision(failureAnalysis)));
279 },
280 length: function()
281 {
282 return this._testFailures.length();
283 },
284 onBlame: function(failure, commitData)
285 {
286 failure.pinToCommitData(commitData);
287 $('.action', failure).each(function() {
288 // FIXME: This isn't the right way of finding and disabling this act ion.
289 if (this.textContent == 'Blame')
290 this.disabled = true;
291 });
292 },
293 onRollout: function(revision, testNameList)
294 {
295 checkout.rollout(revision, ui.rolloutReasonForTestNameList(testNameList) , $.noop, function() {
296 // FIXME: We should have a better error UI.
297 alert(kCheckoutUnavailableMessage);
298 });
299 }
300 });
301
302 controllers.Failures = base.extends(FailureStreamController, {
303 _resultsFilter: results.expectedFailuresByTest,
304
305 _keyFor: function(failureAnalysis)
306 {
307 return base.dirName(failureAnalysis.testName);
308 },
309 _createFailureView: function(failureAnalysis)
310 {
311 return new ui.notifications.FailingTests();
312 },
313 });
314
315 controllers.FailingBuilders = base.extends(Object, {
316 init: function(view, message)
317 {
318 this._view = view;
319 this._message = message;
320 this._notification = null;
321 },
322 hasFailures: function()
323 {
324 return !!this._notification;
325 },
326 update: function(failuresList)
327 {
328 if (Object.keys(failuresList).length == 0) {
329 if (this._notification) {
330 this._notification.dismiss();
331 this._notification = null;
332 }
333 return;
334 }
335 if (!this._notification) {
336 this._notification = new ui.notifications.BuildersFailing(this._mess age);
337 this._view.add(this._notification);
338 }
339 // FIXME: We should provide regression ranges for the failing builders.
340 // This doesn't seem to happen often enough to worry too much about that , however.
341 this._notification.setFailingBuilders(failuresList);
342 }
343 });
344
345 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698