Buildbot Dashboard: Fix JSHint issue: 'perlTestResults' used out of scope.
[WebKit-https.git] / Tools / BuildSlaveSupport / build.webkit.org-config / public_html / dashboard / Scripts / BuildbotIteration.js
1 /*
2  * Copyright (C) 2013 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 BuildbotIteration = function(queue, id, finished)
27 {
28     BaseObject.call(this);
29
30     console.assert(queue);
31     console.assert(id);
32
33     this.queue = queue;
34     this.id = id;
35
36     this.loaded = false;
37
38     this.layoutTestResults = null;
39     this.javascriptTestResults = null;
40     this.pythonTestResults = null;
41     this.perlTestResults = null;
42     this.bindingTestResults = null;
43
44     this._finished = finished;
45 };
46
47 BaseObject.addConstructorFunctions(BuildbotIteration);
48
49 BuildbotIteration.Event = {
50     Updated: "updated"
51 };
52
53 BuildbotIteration.prototype = {
54     constructor: BuildbotIteration,
55     __proto__: BaseObject.prototype,
56
57     get finished()
58     {
59         return this._finished;
60     },
61
62     set finished(x)
63     {
64         this._finished = x;
65     },
66
67     update: function()
68     {
69         if (this.loaded && this._finished)
70             return;
71
72         function collectTestResults(data, stepName)
73         {
74             var testStep = data.steps.findFirst(function(step) { return step.name === stepName; });
75             if (!testStep)
76                 return null;
77
78             if (testStep.results[0] === 4) {
79                 // This build step was interrupted (perhaps due to the build slave restarting).
80                 return null;
81             }
82
83             var testResults = {};
84
85             if (!("isFinished" in testStep)) {
86                 // The step never even ran, or hasn't finish running.
87                 testResults.finished = false;
88                 return testResults;
89             }
90
91             testResults.finished = true;
92
93             if (!("results" in testStep) || !testStep.results[0]) {
94                 // All tests passed.
95                 testResults.allPassed = true;
96                 return testResults;
97             }
98
99             if (/Exiting early/.test(testStep.results[1][0]))
100                 testResults.tooManyFailures = true;
101
102             function resultSummarizer(matchString, sum, outputLine)
103             {
104                 var match = /^(\d+)\s/.exec(outputLine);
105                 if (!match)
106                     return sum;
107                 if (!outputLine.contains(matchString))
108                     return sum;
109                 if (!sum || sum === -1)
110                     sum = 0;
111                 return sum + parseInt(match[1], 10);
112             }
113
114             testResults.failureCount = testStep.results[1].reduce(resultSummarizer.bind(null, "fail"), undefined);
115             testResults.flakeyCount = testStep.results[1].reduce(resultSummarizer.bind(null, "flake"), undefined);
116             testResults.totalLeakCount = testStep.results[1].reduce(resultSummarizer.bind(null, "total leak"), undefined);
117             testResults.uniqueLeakCount = testStep.results[1].reduce(resultSummarizer.bind(null, "unique leak"), undefined);
118             testResults.newPassesCount = testStep.results[1].reduce(resultSummarizer.bind(null, "new pass"), undefined);
119             testResults.missingCount = testStep.results[1].reduce(resultSummarizer.bind(null, "missing"), undefined);
120
121             if (!testResults.failureCount && !testResults.flakyCount && !testResults.totalLeakCount && !testResults.uniqueLeakCount && !testResults.newPassesCount && !testResults.missingCount) {
122                 // This step exited with a non-zero exit status, but we didn't find any output about the number of failed tests.
123                 // Something must have gone wrong (e.g., timed out and was killed by buildbot).
124                 testResults.errorOccurred = true;
125             }
126
127             return testResults;
128         }
129
130         JSON.load(this.queue.baseURL + "/builds/" + this.id, function(data) {
131             if (!data || !data.properties)
132                 return;
133
134             var openSourceRevisionProperty = data.properties.findFirst(function(property) { return property[0] === "got_revision" || property[0] === "revision" || property[0] === "opensource_got_revision"; });
135             this.openSourceRevision = openSourceRevisionProperty ? parseInt(openSourceRevisionProperty[1], 10) : null;
136
137             var internalRevisionProperty = data.properties.findFirst(function(property) { return property[0] === "internal_got_revision"; });
138             this.internalRevision = internalRevisionProperty ? parseInt(internalRevisionProperty[1], 10) : null;
139
140             if (!this.layoutTestResults || !this.layoutTestResults.finished) {
141                 var layoutTestResults = collectTestResults.call(this, data, "layout-test");
142                 this.layoutTestResults = layoutTestResults ? new BuildbotTestResults(this, layoutTestResults) : null;
143             }
144
145             if (!this.javascriptTestResults || !this.javascriptTestResults.finished) {
146                 var javascriptTestResults = collectTestResults.call(this, data, "jscore-test");
147                 this.javascriptTestResults = javascriptTestResults ? new BuildbotTestResults(this, javascriptTestResults) : null;
148             }
149
150             if (!this.apiTestResults || !this.apiTestResults.finished) {
151                 var apiTestResults = collectTestResults.call(this, data, "run-api-tests");
152                 this.apiTestResults = apiTestResults ? new BuildbotTestResults(this, apiTestResults) : null;
153             }
154
155             if (!this.pythonTestResults || !this.pythonTestResults.finished) {
156                 var pythonTestResults = collectTestResults.call(this, data, "webkitpy-test");
157                 this.pythonTestResults = pythonTestResults ? new BuildbotTestResults(this, pythonTestResults) : null;
158             }
159
160             if (!this.perlTestResults || !this.perlTestResults.finished) {
161                 var perlTestResults = collectTestResults.call(this, data, "webkitperl-test");
162                 this.perlTestResults = perlTestResults ? new BuildbotTestResults(this, perlTestResults) : null;
163             }
164
165             if (!this.bindingTestResults || !this.bindingTestResults.finished) {
166                 var bindingTestResults = collectTestResults.call(this, data, "bindings-generation-tests");
167                 this.bindingTestResults = bindingTestResults ? new BuildbotTestResults(this, bindingTestResults) : null;
168             }
169
170             this.loaded = true;
171
172             this.failed = !!data.results;
173
174             if (!data.currentStep)
175                 this.finished = true;
176
177             this.dispatchEventToListeners(BuildbotIteration.Event.Updated);
178         }.bind(this));
179     }
180 };