c14e65b27585c99c9bcf638da2c38ac2dc5f189a
[WebKit-https.git] / PerformanceTests / Animometer / runner / resources / animometer.js
1 window.benchmarkRunnerClient = {
2     iterationCount: 1,
3     testsCount: null,
4     progressBar: null,
5     recordTable: null,
6     options: null,
7     score: 0,
8     _resultsDashboard: null,
9     _resultsTable: null,
10     
11     initialize: function(suites, options)
12     {
13         this.testsCount = this.iterationCount * suites.reduce(function (count, suite) { return count + suite.tests.length; }, 0);
14         this.options = options;
15     },
16
17     willAddTestFrame: function (frame)
18     {
19         var main = document.querySelector("main");
20         var style = getComputedStyle(main);
21         frame.style.left = main.offsetLeft + parseInt(style.borderLeftWidth) + parseInt(style.paddingLeft) + "px";
22         frame.style.top = main.offsetTop + parseInt(style.borderTopWidth) + parseInt(style.paddingTop) + "px";
23     },
24     
25     didRunTest: function ()
26     {
27         this.progressBar.incRange();
28     },
29     
30     willStartFirstIteration: function ()
31     {
32         this._resultsDashboard = new ResultsDashboard();
33         this._resultsTable = new ResultsTable(document.querySelector("section#results > data > table"), Headers);
34         
35         this.progressBar = new ProgressBar(document.getElementById("progress-completed"), this.testsCount);
36         this.recordTable = new ResultsTable(document.querySelector("section#running > #record > table"), Headers);
37     },
38     
39     didRunSuites: function (suitesSamplers)
40     {
41         this._resultsDashboard.push(suitesSamplers);
42     },
43     
44     didFinishLastIteration: function ()
45     {
46         var json = this._resultsDashboard.toJSON(true, true);
47         this.score = json[Strings["JSON_SCORE"]];
48         this._resultsTable.showIterations(json[Strings["JSON_RESULTS"][0]]);
49         sectionsManager.showJSON("json", json[Strings["JSON_RESULTS"][0]][0]);
50         benchmarkController.showResults();
51     }
52 }
53
54 window.sectionsManager =
55 {
56     _sectionHeaderH1Element: function(sectionIdentifier)
57     {
58         return document.querySelector("#" + sectionIdentifier + " > header > h1");
59     },
60     
61     _sectionDataDivElement: function(sectionIdentifier)
62     {
63         return document.querySelector("#" + sectionIdentifier + " >  data > div");
64     },
65     
66     showScore: function(sectionIdentifier, title)
67     {
68         var element = this._sectionHeaderH1Element(sectionIdentifier);
69         element.textContent = title + ":";
70
71         var score = benchmarkRunnerClient.score.toFixed(2);
72         element.textContent += " [Score = " + score + "]";
73     },
74     
75     showTestName: function(sectionIdentifier, title, testName)
76     {
77         var element = this._sectionHeaderH1Element(sectionIdentifier);
78         element.textContent = title + ":";
79
80         if (!testName.length)
81             return;
82             
83         element.textContent += " [test = " + testName + "]";
84     },
85     
86     showJSON: function(sectionIdentifier, json)
87     {
88         var element = this._sectionDataDivElement(sectionIdentifier);
89         element.textContent = JSON.stringify(json, function(key, value) { 
90             if (typeof value == "number")
91                 return value.toFixed(2);
92             return value;
93         }, 4);
94     },
95     
96     showSection: function(sectionIdentifier, pushState)
97     {
98         var currentSectionElement = document.querySelector("section.selected");
99         console.assert(currentSectionElement);
100
101         var newSectionElement = document.getElementById(sectionIdentifier);
102         console.assert(newSectionElement);
103
104         currentSectionElement.classList.remove("selected");
105         newSectionElement.classList.add("selected");
106
107         if (pushState)
108             history.pushState({section: sectionIdentifier}, document.title);
109     },
110
111     setupSectionStyle: function()
112     {
113         if (screen.width >= 1800 && screen.height >= 1000)
114             DocumentExtension.insertCssRuleAfter(" section { width: 1600px; height: 800px; }", "section");
115         else
116             DocumentExtension.insertCssRuleAfter(" section { width: 800px; height: 600px; }", "section");
117     },
118     
119     setupRunningSectionStyle: function(options)
120     {
121         if (!options["show-running-results"])
122             document.getElementById("record").style.display = "none";
123
124         if (options["normalize-for-device-scale-factor"] && window.devicePixelRatio != 1) {
125             var percentage = window.devicePixelRatio * 100;
126             var rule = "section#running > #running-test > iframe";
127             var newRule = rule;
128             newRule += " { ";
129             newRule += "width: " + percentage + "%; ";
130             newRule += "height: " + percentage + "%; ";
131             newRule += "transform: scale(" + 100 / percentage + ") translate(" + (100 - percentage) / 2 + "%," + (100 - percentage) / 2 + "%);";
132             newRule += " }";
133             DocumentExtension.insertCssRuleAfter(newRule, rule);
134         }
135     }
136 }
137
138 window.optionsManager =
139 {
140     _optionsElements : function()
141     {
142         return document.querySelectorAll("section#home > options input");;
143     },
144     
145     updateUIFromLocalStorage: function()
146     {
147         var optionsElements = this._optionsElements();
148
149         for (var i = 0; i < optionsElements.length; ++i) {
150             var optionElement = optionsElements[i];
151             
152             var value = localStorage.getItem(optionElement.id);
153             if (value === null)
154                 continue;
155
156             if (optionElement.getAttribute("type") == "number")
157                 optionElement.value = +value;
158             else if (optionElement.getAttribute("type") == "checkbox")
159                 optionElement.checked = value == "true";
160         }
161     },
162
163     updateLocalStorageFromUI: function()
164     {
165         var optionsElements = this._optionsElements();
166         var options = {};        
167
168         for (var i = 0; i < optionsElements.length; ++i) {
169             var optionElement = optionsElements[i];
170         
171             if (optionElement.getAttribute("type") == "number")
172                 options[optionElement.id] = optionElement.value;
173             else if (optionElement.getAttribute("type") == "checkbox")
174                 options[optionElement.id] = optionElement.checked;
175     
176             localStorage.setItem(optionElement.id, options[optionElement.id]);
177         }
178         
179         return options;
180     }
181 }
182
183 window.suitesManager =
184 {
185     _treeElement : function()
186     {
187         return document.querySelector("suites > .tree");
188     },
189     
190     _suitesElements : function()
191     {
192         return document.querySelectorAll("#home > suites > ul > li");
193     },
194     
195     _checkboxElement: function(element)
196     {
197         return element.querySelector("input[type='checkbox']:not(.expand-button)");
198     },
199
200     _localStorageNameForTest: function(suite, test)
201     {
202         return suite.name + "/" + test.name;
203     },
204
205     _updateSuiteCheckboxState: function(suiteCheckbox)
206     {
207         var numberEnabledTests = 0;
208         suiteCheckbox.testsElements.forEach(function(testElement) {
209             var testCheckbox = this._checkboxElement(testElement);
210             if (testCheckbox.checked)
211                 ++numberEnabledTests;
212         }, this);
213         suiteCheckbox.checked = numberEnabledTests > 0;
214         suiteCheckbox.indeterminate = numberEnabledTests > 0 && numberEnabledTests < suiteCheckbox.testsElements.length;
215     },
216
217     _updateStartButtonState: function()
218     {
219         var suitesElements = this._suitesElements();
220         var startButton = document.querySelector("#home > footer > button");
221         
222         for (var i = 0; i < suitesElements.length; ++i) {
223             var suiteElement = suitesElements[i];
224             var suiteCheckbox = this._checkboxElement(suiteElement);
225             
226             if (suiteCheckbox.checked) {
227                 startButton.disabled = false;
228                 return;
229             }
230         }
231     
232         startButton.disabled = true;
233     },
234
235     _onChangeSuiteCheckbox: function(event)
236     {
237         var selected = event.target.checked;
238         event.target.testsElements.forEach(function(testElement) {
239             var testCheckbox = this._checkboxElement(testElement);
240             testCheckbox.checked = selected;        
241         }, this);
242         this._updateStartButtonState();
243     },
244
245     _onChangeTestCheckbox: function(event)
246     {
247         var suiteCheckbox = event.target.suiteCheckbox;
248         this._updateSuiteCheckboxState(suiteCheckbox);
249         this._updateStartButtonState();
250     },
251
252     _createSuiteElement: function(treeElement, suite, id)
253     {
254         var suiteElement = DocumentExtension.createElement("li", {}, treeElement);
255         var expand = DocumentExtension.createElement("input", { type: "checkbox",  class: "expand-button", id: id }, suiteElement);
256         var label = DocumentExtension.createElement("label", { class: "tree-label", for: id }, suiteElement);
257
258         var suiteCheckbox = DocumentExtension.createElement("input", { type: "checkbox" }, label);
259         suiteCheckbox.suite = suite;
260         suiteCheckbox.onchange = this._onChangeSuiteCheckbox.bind(this);
261         suiteCheckbox.testsElements = [];
262
263         label.appendChild(document.createTextNode(" " + suite.name));
264         return suiteElement;
265     },
266
267     _createTestElement: function(listElement, test, suiteCheckbox)
268     {
269         var testElement = DocumentExtension.createElement("li", {}, listElement);
270         var span = DocumentExtension.createElement("span", { class: "tree-label" }, testElement);
271
272         var testCheckbox = DocumentExtension.createElement("input", { type: "checkbox" }, span);
273         testCheckbox.test = test;
274         testCheckbox.onchange = this._onChangeTestCheckbox.bind(this);
275         testCheckbox.suiteCheckbox = suiteCheckbox;
276
277         suiteCheckbox.testsElements.push(testElement);
278         span.appendChild(document.createTextNode(" " + test.name));
279         return testElement;
280     },
281
282     createElements: function()
283     {
284         var treeElement = this._treeElement();
285
286         Suites.forEach(function(suite, index) {
287             var suiteElement = this._createSuiteElement(treeElement, suite, "suite-" + index);
288             var listElement = DocumentExtension.createElement("ul", {}, suiteElement);
289             var suiteCheckbox = this._checkboxElement(suiteElement);
290
291             suite.tests.forEach(function(test) {
292                 var testElement = this._createTestElement(listElement, test, suiteCheckbox);
293             }, this);
294         }, this);
295     },
296     
297     updateUIFromLocalStorage: function()
298     {
299         var suitesElements = this._suitesElements();
300         
301         for (var i = 0; i < suitesElements.length; ++i) {
302             var suiteElement = suitesElements[i];
303             var suiteCheckbox = this._checkboxElement(suiteElement);
304             var suite = suiteCheckbox.suite;
305             
306             suiteCheckbox.testsElements.forEach(function(testElement) {
307                 var testCheckbox = this._checkboxElement(testElement);
308                 var test = testCheckbox.test;
309                 
310                 var str = localStorage.getItem(this._localStorageNameForTest(suite, test));
311                 if (str === null)
312                     return;
313
314                 var value = JSON.parse(str);
315                 testCheckbox.checked = value.checked;
316             }, this);
317
318             this._updateSuiteCheckboxState(suiteCheckbox);
319         }
320         
321         this._updateStartButtonState();
322     },
323
324     updateLocalStorageFromUI: function()
325     {
326         var suitesElements = this._suitesElements();
327         var suites = [];
328         
329         for (var i = 0; i < suitesElements.length; ++i) {
330             var suiteElement = suitesElements[i];
331             var suiteCheckbox = this._checkboxElement(suiteElement);
332             var suite = suiteCheckbox.suite;
333
334             var tests = [];
335             suiteCheckbox.testsElements.forEach(function(testElement) {
336                 var testCheckbox = this._checkboxElement(testElement);
337                 var test = testCheckbox.test;
338                 
339                 if (testCheckbox.checked)
340                     tests.push(test);
341
342                 var value = { checked: testCheckbox.checked }; 
343                 localStorage.setItem(this._localStorageNameForTest(suite, test), JSON.stringify(value));
344             }, this);
345
346             if (tests.length)
347                 suites.push(new Suite(suiteCheckbox.suite.name, tests));
348         }
349
350         return suites;
351     }
352 }
353
354 window.benchmarkController =
355 {
356     initialize: function()
357     {
358         sectionsManager.setupSectionStyle();
359         optionsManager.updateUIFromLocalStorage();
360         suitesManager.createElements();
361         suitesManager.updateUIFromLocalStorage();
362     },
363
364     _runBenchmark: function(suites, options)
365     {
366         benchmarkRunnerClient.initialize(suites, options);
367         var frameContainer = document.querySelector("#running > #running-test");
368         var runner = new BenchmarkRunner(suites, frameContainer || document.body, benchmarkRunnerClient);
369         runner.runMultipleIterations();
370     },
371
372     startTest: function()
373     {
374         var options = optionsManager.updateLocalStorageFromUI();
375         var suites = suitesManager.updateLocalStorageFromUI();
376         sectionsManager.setupRunningSectionStyle(options);
377         this._runBenchmark(suites, options);
378         sectionsManager.showSection("running");
379     },
380     
381     showResults: function()
382     {
383         sectionsManager.showScore("results", Strings["TEXT_RESULTS"][0]);
384         sectionsManager.showSection("results", true);
385     },
386     
387     showJson: function()
388     {
389         sectionsManager.showScore("json", Strings["TEXT_RESULTS"][0]);
390         sectionsManager.showSection("json", true);
391     },
392     
393     showTestGraph: function(testName, axes, samples, samplingTimeOffset)
394     {
395         sectionsManager.showTestName("test-graph", Strings["TEXT_RESULTS"][1], testName);
396         sectionsManager.showSection("test-graph", true);
397         graph("section#test-graph > data", new Insets(20, 50, 20, 50), axes, samples, samplingTimeOffset);
398     },
399
400     showTestJSON: function(testName, json)
401     {
402         sectionsManager.showTestName("test-json", Strings["TEXT_RESULTS"][1], testName);
403         sectionsManager.showJSON("test-json", json);
404         sectionsManager.showSection("test-json", true);
405     }
406 }
407
408 document.addEventListener("DOMContentLoaded", benchmarkController.initialize());