Skip to content

Commit 559aee7

Browse files
committed
Add unit tests for data import, and minor fixes.
Add test-data-import.js which tests creating a `ResultsDashboard` with imported JSON, which is the JSON produced by running the test via the browser. The test validates that the results analysis produces output data in the correct format, but does not validate the score calculation. To make the unit test run faster, we make `bootstrapIterations` be configurable via an option. The unit test sets this to a small value. Fix a bug that prevented the JSON results dialog being shown by using arrow functions in `BenchmarkController` so that `this` is correctly bound.
1 parent d46dee4 commit 559aee7

File tree

6 files changed

+92
-6
lines changed

6 files changed

+92
-6
lines changed

MotionMark/resources/runner/motionmark.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,19 +350,19 @@ class BenchmarkController {
350350

351351
var data = Utilities.createElement("div", {}, container);
352352
data.textContent = "Please wait...";
353-
setTimeout(function() {
353+
setTimeout(() => {
354354
var output = {
355355
version: this.runnerClient.results.version,
356356
options: this.runnerClient.results.options,
357357
data: this.runnerClient.results.data
358358
};
359-
data.textContent = JSON.stringify(output, function(key, value) {
359+
data.textContent = JSON.stringify(output, (key, value) => {
360360
if (typeof value === 'number')
361361
return Utilities.toFixedNumber(value, 3);
362362
return value;
363363
}, 1);
364364
}, 0);
365-
data.onclick = function() {
365+
data.onclick = () => {
366366
var selection = window.getSelection();
367367
selection.removeAllRanges();
368368
var range = document.createRange();
@@ -372,8 +372,8 @@ class BenchmarkController {
372372

373373
var button = Utilities.createElement("button", {}, container);
374374
button.textContent = "Done";
375-
button.onclick = function() {
376-
benchmarkController.hideDebugInfo();
375+
button.onclick = () => {
376+
this.hideDebugInfo();
377377
};
378378
}
379379

MotionMark/resources/runner/results.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class ResultsDashboard {
3232
this._version = version;
3333
this._targetFrameRate = options["frame-rate"];
3434
this._systemFrameRate = options["system-frame-rate"];
35+
36+
const defaultBootstrapIterations = 2500;
37+
if (!Object.hasOwn(this._options, Strings.json.bootstrapIterations))
38+
this._options[Strings.json.bootstrapIterations] = defaultBootstrapIterations;
39+
3540
if (testData) {
3641
this._iterationsSamplers = testData;
3742
this._processData();
@@ -188,7 +193,7 @@ class ResultsDashboard {
188193
experimentResult[Strings.json.measurements.stdev] = timeComplexity.standardDeviation();
189194
experimentResult[Strings.json.measurements.percent] = timeComplexity.percentage();
190195

191-
const bootstrapIterations = 2500;
196+
const bootstrapIterations = this._options[Strings.json.bootstrapIterations];
192197
var bootstrapResult = Regression.bootstrap(regressionResult.samples.data, bootstrapIterations, function(resampleData) {
193198
var complexityIndex = regressionResult.samples.fieldMap[Strings.json.complexity];
194199
resampleData.sort(function(a, b) {

MotionMark/resources/strings.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ var Strings = {
6060
scoreUpperBound: "scoreUpperBound",
6161
fps: "fps",
6262
bootstrap: "bootstrap",
63+
bootstrapIterations: "bootstrapIterations",
6364
measurements: {
6465
average: "average",
6566
concern: "concern",

MotionMark/unit-tests/data/two-suite-single-iteration-test-data.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

MotionMark/unit-tests/run-unit-tests.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<script src="../resources/statistics.js"></script>
1111

1212
<script src="../resources/runner/tests.js"></script>
13+
<script src="../resources/runner/results.js"></script>
1314
<script src="../resources/debug-runner/tests.js"></script>
1415

1516
<script src="../resources/runner/benchmark-runner.js"></script>
@@ -44,6 +45,7 @@ <h1>MotionMark Unit Tests</h1>
4445

4546
<script src="tests/test-random.js"></script>
4647
<script src="tests/test-statistics.js"></script>
48+
<script src="tests/test-data-import.js"></script>
4749

4850
<script class="mocha-exec">
4951
mocha.run();
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright (C) 2024 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+
describe('Data Import', function() {
27+
it('Fetch test data', async function() {
28+
this.timeout(200);
29+
30+
const url = "data/two-suite-single-iteration-test-data.json";
31+
const response = await fetch(url);
32+
expect(response.ok).to.be(true);
33+
34+
this.json = await response.json();
35+
expect(this.json.version).to.be('1.4');
36+
});
37+
38+
it('Validate imported data', function() {
39+
expect(this.json.options instanceof Object).to.be(true);
40+
expect(this.json.data instanceof Array).to.be(true);
41+
});
42+
43+
it('Create results', function() {
44+
this.timeout(500);
45+
46+
// Make the results analysis faster.
47+
this.json.options[Strings.json.bootstrapIterations] = 10;
48+
49+
const dashboard = new ResultsDashboard(this.json.version, this.json.options, this.json.data);
50+
this.results = dashboard.results;
51+
expect(this.results instanceof Array).to.be(true);
52+
});
53+
54+
it('Validate results', function() {
55+
56+
// Check that we have results, not their exact values.
57+
const firstResults = this.results[0];
58+
59+
expect(typeof firstResults[Strings.json.score]).to.be('number');
60+
expect(typeof firstResults[Strings.json.scoreLowerBound]).to.be('number');
61+
expect(typeof firstResults[Strings.json.scoreUpperBound]).to.be('number');
62+
63+
expect(firstResults[Strings.json.results.tests] instanceof Object).to.be(true);
64+
65+
const testsResults = firstResults[Strings.json.results.tests];
66+
expect(testsResults['MotionMark'] instanceof Object).to.be(true);
67+
68+
const motionMarkResults = testsResults['MotionMark'];
69+
expect(motionMarkResults['Multiply'] instanceof Object).to.be(true);
70+
expect(motionMarkResults['Leaves'] instanceof Object).to.be(true);
71+
72+
const multiplyResults = motionMarkResults['Multiply'];
73+
expect(typeof multiplyResults[Strings.json.score]).to.be('number');
74+
expect(typeof multiplyResults[Strings.json.scoreLowerBound]).to.be('number');
75+
expect(typeof multiplyResults[Strings.json.scoreUpperBound]).to.be('number');
76+
});
77+
});

0 commit comments

Comments
 (0)