Update suites for benchmark
[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.iterations], this.options);
49         sectionsManager.showJSON("json", json[Strings.json.results.iterations][0]);
50         suitesManager.updateLocalStorageFromJSON(json[Strings.json.results.iterations][0]);
51         benchmarkController.showResults();
52     }
53 }
54
55 window.sectionsManager =
56 {
57     _sectionHeaderH1Element: function(sectionIdentifier)
58     {
59         return document.querySelector("#" + sectionIdentifier + " > header > h1");
60     },
61
62     _sectionDataElement: function(sectionIdentifier)
63     {
64         return document.querySelector("#" + sectionIdentifier + " > data");
65     },
66     
67     _sectionDataDivElement: function(sectionIdentifier)
68     {
69         return document.querySelector("#" + sectionIdentifier + " >  data > div");
70     },
71     
72     showScore: function(sectionIdentifier, title)
73     {
74         var element = this._sectionHeaderH1Element(sectionIdentifier);
75         element.textContent = title + ":";
76
77         var score = benchmarkRunnerClient.score.toFixed(2);
78         element.textContent += " [" + Strings.text.score + " = " + score + "]";
79     },
80     
81     showTestName: function(sectionIdentifier, title, testName)
82     {
83         var element = this._sectionHeaderH1Element(sectionIdentifier);
84         element.textContent = title + ":";
85
86         if (!testName.length)
87             return;
88             
89         element.textContent += " [" + Strings.text.testName + " = " + testName + "]";
90     },
91     
92     showJSON: function(sectionIdentifier, json)
93     {
94         var element = this._sectionDataDivElement(sectionIdentifier);
95         element.textContent = JSON.stringify(json, function(key, value) { 
96             if (typeof value == "number")
97                 return value.toFixed(2);
98             return value;
99         }, 4);
100     },
101     
102     selectData: function(sectionIdentifier)
103     {
104         window.getSelection().removeAllRanges();
105         var element = this._sectionDataElement(sectionIdentifier);
106         var range = document.createRange();
107         range.selectNode(element);
108         window.getSelection().addRange(range);  
109     },
110     
111     selectDataContents: function(sectionIdentifier)
112     {
113         window.getSelection().removeAllRanges();
114         var element = this._sectionDataDivElement(sectionIdentifier);
115         var range = document.createRange();
116         range.selectNodeContents(element);
117         window.getSelection().addRange(range);
118     },
119         
120     showSection: function(sectionIdentifier, pushState)
121     {
122         var currentSectionElement = document.querySelector("section.selected");
123         console.assert(currentSectionElement);
124
125         var newSectionElement = document.getElementById(sectionIdentifier);
126         console.assert(newSectionElement);
127
128         currentSectionElement.classList.remove("selected");
129         newSectionElement.classList.add("selected");
130
131         if (pushState)
132             history.pushState({section: sectionIdentifier}, document.title);
133     },
134
135     setupRunningSectionStyle: function(options)
136     {
137         if (options["display"] != "statistics-table")
138             document.getElementById("record").style.display = "none";
139     }
140 }
141
142 window.optionsManager =
143 {
144     valueForOption: function(name)
145     {
146         var formElement = document.forms["benchmark-options"].elements[name];
147         if (formElement.type == "checkbox")
148             return formElement.checked;
149         return formElement.value;
150     },
151     
152     updateUIFromLocalStorage: function()
153     {
154         var formElements = document.forms["benchmark-options"].elements;
155
156         for (var i = 0; i < formElements.length; ++i) {
157             var formElement = formElements[i];
158             var name = formElement.id || formElement.name;
159             var type = formElement.type;
160
161             var value = localStorage.getItem(name);
162             if (value === null)
163                 continue;
164
165             if (type == "number")
166                 formElements[name].value = +value;
167             else if (type == "checkbox")
168                 formElements[name].checked = value == "true";
169             else if (type == "radio")
170                 formElements[name].value = value;
171         }
172     },
173
174     updateLocalStorageFromUI: function()
175     {
176         var formElements = document.forms["benchmark-options"].elements;
177         var options = {};        
178
179         for (var i = 0; i < formElements.length; ++i) {
180             var formElement = formElements[i];
181             var name = formElement.id || formElement.name;
182             var type = formElement.type;
183
184             if (type == "number")
185                 options[name] = formElement.value;
186             else if (type == "checkbox")
187                 options[name] = formElement.checked;
188             else if (type == "radio")
189                 options[name] = formElements[name].value;
190     
191             localStorage.setItem(name, options[name]);
192         }
193         
194         return options;
195     }
196 }
197
198 window.suitesManager =
199 {
200     _treeElement: function()
201     {
202         return document.querySelector("#suites > .tree");
203     },
204     
205     _suitesElements: function()
206     {
207         return document.querySelectorAll("#suites > ul > li");
208     },
209     
210     _checkboxElement: function(element)
211     {
212         return element.querySelector("input[type='checkbox']:not(.expand-button)");
213     },
214
215     _editElement: function(element)
216     {
217         return element.querySelector("input[type='number']");
218     },
219
220     _editsElements: function()
221     {
222         return document.querySelectorAll("#suites input[type='number']");
223     },
224         
225     _localStorageNameForTest: function(suiteName, testName)
226     {
227         return suiteName + "/" + testName;
228     },
229
230     _updateSuiteCheckboxState: function(suiteCheckbox)
231     {
232         var numberEnabledTests = 0;
233         suiteCheckbox.testsElements.forEach(function(testElement) {
234             var testCheckbox = this._checkboxElement(testElement);
235             if (testCheckbox.checked)
236                 ++numberEnabledTests;
237         }, this);
238         suiteCheckbox.checked = numberEnabledTests > 0;
239         suiteCheckbox.indeterminate = numberEnabledTests > 0 && numberEnabledTests < suiteCheckbox.testsElements.length;
240     },
241
242     _updateStartButtonState: function()
243     {
244         var suitesElements = this._suitesElements();
245         var startButton = document.querySelector("#home > footer > button");
246         
247         for (var i = 0; i < suitesElements.length; ++i) {
248             var suiteElement = suitesElements[i];
249             var suiteCheckbox = this._checkboxElement(suiteElement);
250             
251             if (suiteCheckbox.checked) {
252                 startButton.disabled = false;
253                 return;
254             }
255         }
256     
257         startButton.disabled = true;
258     },
259
260     _onChangeSuiteCheckbox: function(event)
261     {
262         var selected = event.target.checked;
263         event.target.testsElements.forEach(function(testElement) {
264             var testCheckbox = this._checkboxElement(testElement);
265             testCheckbox.checked = selected;        
266         }, this);
267         this._updateStartButtonState();
268     },
269
270     _onChangeTestCheckbox: function(event)
271     {
272         var suiteCheckbox = event.target.suiteCheckbox;
273         this._updateSuiteCheckboxState(suiteCheckbox);
274         this._updateStartButtonState();
275     },
276
277     _createSuiteElement: function(treeElement, suite, id)
278     {
279         var suiteElement = DocumentExtension.createElement("li", {}, treeElement);
280         var expand = DocumentExtension.createElement("input", { type: "checkbox",  class: "expand-button", id: id }, suiteElement);
281         var label = DocumentExtension.createElement("label", { class: "tree-label", for: id }, suiteElement);
282
283         var suiteCheckbox = DocumentExtension.createElement("input", { type: "checkbox" }, label);
284         suiteCheckbox.suite = suite;
285         suiteCheckbox.onchange = this._onChangeSuiteCheckbox.bind(this);
286         suiteCheckbox.testsElements = [];
287
288         label.appendChild(document.createTextNode(" " + suite.name));
289         return suiteElement;
290     },
291
292     _createTestElement: function(listElement, test, suiteCheckbox)
293     {
294         var testElement = DocumentExtension.createElement("li", {}, listElement);
295         var span = DocumentExtension.createElement("label", { class: "tree-label" }, testElement);
296
297         var testCheckbox = DocumentExtension.createElement("input", { type: "checkbox" }, span);
298         testCheckbox.test = test;
299         testCheckbox.onchange = this._onChangeTestCheckbox.bind(this);
300         testCheckbox.suiteCheckbox = suiteCheckbox;
301
302         suiteCheckbox.testsElements.push(testElement);
303         span.appendChild(document.createTextNode(" " + test.name));
304         DocumentExtension.createElement("input", { type: "number" }, testElement);
305         return testElement;
306     },
307
308     createElements: function()
309     {
310         var treeElement = this._treeElement();
311
312         Suites.forEach(function(suite, index) {
313             var suiteElement = this._createSuiteElement(treeElement, suite, "suite-" + index);
314             var listElement = DocumentExtension.createElement("ul", {}, suiteElement);
315             var suiteCheckbox = this._checkboxElement(suiteElement);
316
317             suite.tests.forEach(function(test) {
318                 var testElement = this._createTestElement(listElement, test, suiteCheckbox);
319             }, this);
320         }, this);
321     },
322     
323     updateEditsElementsState: function()
324     {
325         var editsElements = this._editsElements();
326         var showComplexityInputs = optionsManager.valueForOption("adjustment") == "fixed";
327
328         for (var i = 0; i < editsElements.length; ++i) {
329             var editElement = editsElements[i];
330             if (showComplexityInputs)
331                 editElement.classList.add("selected");
332             else
333                 editElement.classList.remove("selected");
334         }
335     },
336
337     updateDisplay: function()
338     {
339         document.body.className = "display-" + optionsManager.valueForOption("display");
340     },
341
342     updateUIFromLocalStorage: function()
343     {
344         var suitesElements = this._suitesElements();
345         
346         for (var i = 0; i < suitesElements.length; ++i) {
347             var suiteElement = suitesElements[i];
348             var suiteCheckbox = this._checkboxElement(suiteElement);
349             var suite = suiteCheckbox.suite;
350             
351             suiteCheckbox.testsElements.forEach(function(testElement) {
352                 var testCheckbox = this._checkboxElement(testElement);
353                 var testEdit = this._editElement(testElement);
354                 var test = testCheckbox.test;
355                 
356                 var str = localStorage.getItem(this._localStorageNameForTest(suite.name, test.name));
357                 if (str === null)
358                     return;
359
360                 var value = JSON.parse(str);
361                 testCheckbox.checked = value.checked;
362                 testEdit.value = value.complexity;
363             }, this);
364
365             this._updateSuiteCheckboxState(suiteCheckbox);
366         }
367         
368         this._updateStartButtonState();
369     },
370
371     updateLocalStorageFromUI: function()
372     {
373         var suitesElements = this._suitesElements();
374         var suites = [];
375         
376         for (var i = 0; i < suitesElements.length; ++i) {
377             var suiteElement = suitesElements[i];
378             var suiteCheckbox = this._checkboxElement(suiteElement);
379             var suite = suiteCheckbox.suite;
380
381             var tests = [];
382             suiteCheckbox.testsElements.forEach(function(testElement) {
383                 var testCheckbox = this._checkboxElement(testElement);
384                 var testEdit = this._editElement(testElement);
385                 var test = testCheckbox.test;
386                 
387                 if (testCheckbox.checked) {
388                     test.complexity = testEdit.value;
389                     tests.push(test);
390                 }
391
392                 var value = { checked: testCheckbox.checked, complexity: testEdit.value }; 
393                 localStorage.setItem(this._localStorageNameForTest(suite.name, test.name), JSON.stringify(value));
394             }, this);
395
396             if (tests.length)
397                 suites.push(new Suite(suiteCheckbox.suite.name, tests));
398         }
399
400         return suites;
401     },
402     
403     updateLocalStorageFromJSON: function(iterationResults)
404     {
405         for (var suiteName in iterationResults[Strings.json.results.suites]) {
406             var suiteResults = iterationResults[Strings.json.results.suites][suiteName];
407
408             for (var testName in suiteResults[Strings.json.results.tests]) {
409                 var testResults = suiteResults[Strings.json.results.tests][testName];
410                 var data = testResults[Strings.json.experiments.complexity];
411                 var complexity = Math.round(data[Strings.json.measurements.average]);
412
413                 var value = { checked: true, complexity: complexity };
414                 localStorage.setItem(this._localStorageNameForTest(suiteName, testName), JSON.stringify(value));
415             }
416         }
417     }
418 }
419
420 window.benchmarkController =
421 {
422     initialize: function()
423     {
424         document.forms["benchmark-options"].addEventListener("change", benchmarkController.onFormChanged, true);
425         optionsManager.updateUIFromLocalStorage();
426         suitesManager.createElements();
427         suitesManager.updateUIFromLocalStorage();
428         suitesManager.updateDisplay();
429         suitesManager.updateEditsElementsState();
430     },
431
432     onFormChanged: function(event)
433     {
434         if (event.target.name == "adjustment") {
435             suitesManager.updateEditsElementsState();
436             return;
437         }
438         if (event.target.name == "display") {
439             suitesManager.updateDisplay();
440         }
441     },
442     
443     _runBenchmark: function(suites, options)
444     {
445         benchmarkRunnerClient.initialize(suites, options);
446         var frameContainer = document.querySelector("#running > #running-test");
447         var runner = new BenchmarkRunner(suites, frameContainer || document.body, benchmarkRunnerClient);
448         runner.runMultipleIterations();
449     },
450
451     startTest: function()
452     {
453         var options = optionsManager.updateLocalStorageFromUI();
454         var suites = suitesManager.updateLocalStorageFromUI();
455         sectionsManager.setupRunningSectionStyle(options);
456         this._runBenchmark(suites, options);
457         sectionsManager.showSection("running");
458     },
459
460     selectResults: function()
461     {
462         sectionsManager.selectData("results");
463     },
464     
465     showResults: function()
466     {
467         sectionsManager.showScore("results", Strings.text.results.results);
468         sectionsManager.showSection("results", true);
469     },
470     
471     showJSON: function()
472     {
473         sectionsManager.showScore("json", Strings.text.results.results);
474         sectionsManager.showSection("json", true);
475     },
476
477     showTestGraph: function(testName, axes, samples, samplingTimeOffset)
478     {
479         sectionsManager.showTestName("test-graph", Strings.text.results.graph, testName);
480         sectionsManager.showSection("test-graph", true);
481         graph("section#test-graph > data", new Insets(20, 50, 20, 50), axes, samples, samplingTimeOffset);
482     },
483
484     showTestJSON: function(testName, json)
485     {
486         sectionsManager.showTestName("test-json", Strings.text.results.graph, testName);
487         sectionsManager.showJSON("test-json", json);
488         sectionsManager.showSection("test-json", true);
489     },
490     
491     selectJSON: function(sectionIdentifier)
492     {
493         sectionsManager.selectDataContents(sectionIdentifier);
494     },
495 }
496
497 window.addEventListener("load", benchmarkController.initialize);