96bf594d1222405651a248732ca948db0b964159
[WebKit-https.git] / Tools / BuildSlaveSupport / build.webkit.org-config / public_html / TestFailures / LayoutTestHistoryAnalyzer.js
1 /*
2  * Copyright (C) 2011 Apple 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 function LayoutTestHistoryAnalyzer(builder) {
27     this._builder = builder;
28     this._history = {};
29     this._loader = new LayoutTestResultsLoader(builder);
30 }
31
32 LayoutTestHistoryAnalyzer.prototype = {
33     /*
34      * Preiodically calls callback until all current failures have been explained. Callback is
35      * passed an object like the following:
36      * {
37      *     'r12347 (681)': {
38      *         'tooManyFailures': false,
39      *         'tests': {
40      *             'css1/basic/class_as_selector2.html': 'fail',
41      *         },
42      *     },
43      *     'r12346 (680)': {
44      *         'tooManyFailures': false,
45      *         'tests': {},
46      *     },
47      *     'r12345 (679)': {
48      *         'tooManyFailures': false,
49      *         'tests': {
50      *             'css1/basic/class_as_selector.html': 'crash',
51      *         },
52      *     },
53      * },
54      * Each build contains just the failures that a) are still occuring on the bots, and b) were new
55      * in that build.
56      */
57     start: function(callback) {
58         var self = this;
59         self._builder.getBuildNames(function(buildNames) {
60             function inner(buildIndex) {
61                 self._incorporateBuildHistory(buildNames, buildIndex, function(callAgain) {
62                     var nextIndex = buildIndex + 1;
63                     if (nextIndex >= buildNames.length)
64                         callAgain = false;
65                     callback(self._history, callAgain);
66                     if (!callAgain)
67                         return;
68                     setTimeout(function() { inner(nextIndex) }, 0);
69                 });
70             }
71             inner(0);
72         });
73     },
74
75     _incorporateBuildHistory: function(buildNames, buildIndex, callback) {
76         var previousBuildName = Object.keys(this._history).last();
77         var nextBuildName = buildNames[buildIndex];
78
79         var self = this;
80         self._loader.start(nextBuildName, function(tests, tooManyFailures) {
81             self._history[nextBuildName] = {
82                 tooManyFailures: tooManyFailures,
83                 tests: {},
84             };
85
86             for (var testName in tests) {
87                 if (previousBuildName) {
88                     if (!(testName in self._history[previousBuildName].tests))
89                         continue;
90                     delete self._history[previousBuildName].tests[testName];
91                 }
92                 self._history[nextBuildName].tests[testName] = tests[testName];
93             }
94
95             callback(Object.keys(self._history[nextBuildName].tests).length);
96         },
97         function(tests) {
98             // Some tests failed, but we couldn't fetch results.html (perhaps because the test
99             // run aborted early for some reason). Just skip this build entirely.
100             callback(true);
101         });
102     },
103 };