summaryrefslogtreecommitdiffstats
path: root/dom/performance/tests
diff options
context:
space:
mode:
Diffstat (limited to 'dom/performance/tests')
-rw-r--r--dom/performance/tests/mochitest.ini17
-rw-r--r--dom/performance/tests/performance_observer.html74
-rw-r--r--dom/performance/tests/sharedworker_performance_user_timing.js30
-rw-r--r--dom/performance/tests/test_performance_observer.html17
-rw-r--r--dom/performance/tests/test_performance_observer.js226
-rw-r--r--dom/performance/tests/test_performance_user_timing.html45
-rw-r--r--dom/performance/tests/test_performance_user_timing.js272
-rw-r--r--dom/performance/tests/test_sharedWorker_performance_user_timing.html27
-rw-r--r--dom/performance/tests/test_worker_observer.html17
-rw-r--r--dom/performance/tests/test_worker_performance_now.html32
-rw-r--r--dom/performance/tests/test_worker_performance_now.js76
-rw-r--r--dom/performance/tests/test_worker_user_timing.html27
-rw-r--r--dom/performance/tests/worker_performance_observer.html32
-rw-r--r--dom/performance/tests/worker_performance_observer.js4
-rw-r--r--dom/performance/tests/worker_performance_user_timing.js24
15 files changed, 920 insertions, 0 deletions
diff --git a/dom/performance/tests/mochitest.ini b/dom/performance/tests/mochitest.ini
new file mode 100644
index 000000000..18f7f0e45
--- /dev/null
+++ b/dom/performance/tests/mochitest.ini
@@ -0,0 +1,17 @@
+[DEFAULT]
+support-files =
+ performance_observer.html
+ test_performance_observer.js
+ test_performance_user_timing.js
+ test_worker_performance_now.js
+ worker_performance_user_timing.js
+ worker_performance_observer.js
+ sharedworker_performance_user_timing.js
+ worker_performance_observer.html
+
+[test_performance_observer.html]
+[test_performance_user_timing.html]
+[test_worker_user_timing.html]
+[test_worker_observer.html]
+[test_sharedWorker_performance_user_timing.html]
+[test_worker_performance_now.html]
diff --git a/dom/performance/tests/performance_observer.html b/dom/performance/tests/performance_observer.html
new file mode 100644
index 000000000..b8ced9296
--- /dev/null
+++ b/dom/performance/tests/performance_observer.html
@@ -0,0 +1,74 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<meta charset=utf-8>
+<html>
+<head>
+<title>Test for performance observer</title>
+<script>
+'use strict';
+[
+ "promise_test", "test", "setup",
+ "assert_true", "assert_equals", "assert_array_equals",
+ "assert_throws", "assert_unreached"
+].forEach(func => {
+ window[func] = opener[func].bind(opener);
+});
+function done() {
+ opener.add_completion_callback(() => {
+ self.close();
+ });
+ opener.done();
+}
+
+</script>
+<script src="test_performance_observer.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+function makeXHR(aUrl) {
+ var xmlhttp = new XMLHttpRequest();
+ xmlhttp.open("get", aUrl, true);
+ xmlhttp.send();
+}
+
+promise_test(t => {
+ var promise = new Promise(resolve => {
+ performance.clearResourceTimings();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe({entryTypes: ['resource']});
+ t.add_cleanup(() => observer.disconnect());
+ });
+
+ makeXHR("test-data.json");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 1);
+ assert_array_equals(list.getEntries(),
+ performance.getEntriesByType("resource"),
+ "Observed 'resource' entries should equal to entries obtained by getEntriesByType.");
+
+ // getEntries filtering tests
+ assert_array_equals(list.getEntries({name: "http://mochi.test:8888/tests/dom/base/test/test-data.json"}),
+ performance.getEntriesByName("http://mochi.test:8888/tests/dom/base/test/test-data.json"),
+ "getEntries with name filter should return correct results.");
+ assert_array_equals(list.getEntries({entryType: "resource"}),
+ performance.getEntriesByType("resource"),
+ "getEntries with entryType filter should return correct results.");
+ assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
+ performance.getEntriesByType("resource"),
+ "getEntries with initiatorType filter should return correct results.");
+ assert_array_equals(list.getEntries({initiatorType: "link"}),
+ [],
+ "getEntries with non-existent initiatorType filter should return an empty array.");
+ });
+}, "resource-timing test");
+
+done();
+
+</script>
+</body>
diff --git a/dom/performance/tests/sharedworker_performance_user_timing.js b/dom/performance/tests/sharedworker_performance_user_timing.js
new file mode 100644
index 000000000..ced3e95fa
--- /dev/null
+++ b/dom/performance/tests/sharedworker_performance_user_timing.js
@@ -0,0 +1,30 @@
+var port;
+
+function ok(a, msg) {
+ dump("OK: " + !!a + " => " + a + " " + msg + "\n");
+ port.postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+ dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
+ port.postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
+}
+
+function isnot(a, b, msg) {
+ dump("ISNOT: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
+ port.postMessage({type: 'status', status: a != b, msg: a + " != " + b + ": " + msg });
+}
+
+importScripts('test_performance_user_timing.js');
+
+onconnect = function(evt) {
+ port = evt.ports[0];
+
+ for (var i = 0; i < steps.length; ++i) {
+ performance.clearMarks();
+ performance.clearMeasures();
+ steps[i]();
+ }
+
+ port.postMessage({type: 'finish'});
+}
diff --git a/dom/performance/tests/test_performance_observer.html b/dom/performance/tests/test_performance_observer.html
new file mode 100644
index 000000000..d36878315
--- /dev/null
+++ b/dom/performance/tests/test_performance_observer.html
@@ -0,0 +1,17 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for performance observer</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+'use strict';
+SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
+ function() {
+ window.open("performance_observer.html");
+ });
+</script>
diff --git a/dom/performance/tests/test_performance_observer.js b/dom/performance/tests/test_performance_observer.js
new file mode 100644
index 000000000..9716570e2
--- /dev/null
+++ b/dom/performance/tests/test_performance_observer.js
@@ -0,0 +1,226 @@
+setup({ explicit_done: true });
+
+test(t => {
+ assert_throws({name: "TypeError"}, function() {
+ new PerformanceObserver();
+ }, "PerformanceObserver constructor should throw TypeError if no argument is specified.");
+
+ assert_throws({name: "TypeError"}, function() {
+ new PerformanceObserver({});
+ }, "PerformanceObserver constructor should throw TypeError if the argument is not a function.");
+}, "Test that PerformanceObserver constructor throws exception");
+
+test(t => {
+ var observer = new PerformanceObserver(() => {
+ });
+
+ assert_throws({name: "TypeError"}, function() {
+ observer.observe();
+ }, "observe() should throw TypeError exception if no option specified.");
+
+ assert_throws({name: "TypeError"}, function() {
+ observer.observe({ unsupportedAttribute: "unsupported" });
+ }, "obsrve() should throw TypeError exception if the option has no 'entryTypes' attribute.");
+
+ assert_throws({name: "TypeError"}, function() {
+ observer.observe({ entryTypes: [] });
+ }, "obsrve() should throw TypeError exception if 'entryTypes' attribute is an empty sequence.");
+
+ assert_throws({name: "TypeError"}, function() {
+ observer.observe({ entryTypes: null });
+ }, "obsrve() should throw TypeError exception if 'entryTypes' attribute is null.");
+
+ assert_throws({name: "TypeError"}, function() {
+ observer.observe({ entryTypes: ["invalid"]});
+ }, "obsrve() should throw TypeError exception if 'entryTypes' attribute value is invalid.");
+}, "Test that PerformanceObserver.observe throws exception");
+
+function promiseObserve(test, options) {
+ return new Promise(resolve => {
+ performance.clearMarks();
+ performance.clearMeasures();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe(options);
+ test.add_cleanup(() => observer.disconnect());
+ });
+}
+
+promise_test(t => {
+ var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
+
+ performance.mark("test-start");
+ performance.mark("test-end");
+ performance.measure("test-measure", "test-start", "test-end");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 3,
+ "There should be three observed entries.");
+
+ var markEntries = list.getEntries().filter(entry => {
+ return entry.entryType == "mark";
+ });
+ assert_array_equals(markEntries, performance.getEntriesByType("mark"),
+ "Observed 'mark' entries should equal to entries obtained by getEntriesByType.");
+
+ var measureEntries = list.getEntries().filter(entry => {
+ return entry.entryType == "measure";
+ });
+ assert_array_equals(measureEntries, performance.getEntriesByType("measure"),
+ "Observed 'measure' entries should equal to entries obtained by getEntriesByType.");
+ });
+}, "Test for user-timing with PerformanceObserver");
+
+promise_test(t => {
+ var promise = new Promise((resolve, reject) => {
+ performance.clearMarks();
+ performance.clearMeasures();
+
+ var observer = new PerformanceObserver(list => reject(list));
+ observer.observe({entryTypes: ['mark', 'measure']});
+ observer.disconnect();
+ t.step_timeout(resolve, 100);
+ });
+
+ performance.mark("test-start");
+ performance.mark("test-end");
+ performance.measure("test-measure", "test-start", "test-end");
+
+ return promise.then(() => {
+ assert_equals(performance.getEntriesByType("mark").length, 2);
+ assert_equals(performance.getEntriesByType("measure").length, 1);
+ }, list => {
+ assert_unreached("Observer callback should never be called.");
+ });
+
+}, "Nothing should be notified after disconnecting observer");
+
+promise_test(t => {
+ var promise = promiseObserve(t, {entryTypes: ['mark']});
+
+ performance.mark("test");
+
+ return promise.then(list => {
+ assert_array_equals(list.getEntries({"entryType": "mark"}),
+ performance.getEntriesByType("mark"),
+ "getEntries with entryType filter should return correct results.");
+
+ assert_array_equals(list.getEntries({"name": "test"}),
+ performance.getEntriesByName("test"),
+ "getEntries with name filter should return correct results.");
+
+ assert_array_equals(list.getEntries({"name": "test",
+ "entryType": "mark"}),
+ performance.getEntriesByName("test"),
+ "getEntries with name and entryType filter should return correct results.");
+
+ assert_array_equals(list.getEntries({"name": "invalid"}),
+ [],
+ "getEntries with non-existent name filter should return an empty array.");
+
+ assert_array_equals(list.getEntries({"name": "test",
+ "entryType": "measure"}),
+ [],
+ "getEntries with name filter and non-existent entryType should return an empty array.");
+
+ assert_array_equals(list.getEntries({"name": "invalid",
+ "entryType": "mark"}),
+ [],
+ "getEntries with non-existent name and entryType filter should return an empty array.");
+
+ assert_array_equals(list.getEntries({initiatorType: "xmlhttprequest"}),
+ [],
+ "getEntries with initiatorType filter should return an empty array.");
+ });
+}, "Test for PerformanceObserverEntryList.getEntries");
+
+promise_test(t => {
+ var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
+
+ performance.mark("test");
+ performance.measure("test-measure", "test", "test");
+
+ return promise.then(list => {
+ assert_array_equals(list.getEntriesByType("mark"),
+ performance.getEntriesByType("mark"));
+ assert_array_equals(list.getEntriesByType("measure"),
+ performance.getEntriesByType("measure"));
+ });
+}, "Test for PerformanceObserverEntryList.getEntriesByType");
+
+promise_test(t => {
+ var promise = promiseObserve(t, {entryTypes: ['mark', 'measure']});
+
+ performance.mark("test");
+ performance.measure("test-measure", "test", "test");
+
+ return promise.then(list => {
+ assert_array_equals(list.getEntriesByName("test"),
+ performance.getEntriesByName("test"));
+ assert_array_equals(list.getEntriesByName("test-measure"),
+ performance.getEntriesByName("test-measure"));
+ });
+}, "Test for PerformanceObserverEntryList.getEntriesByName");
+
+promise_test(t => {
+ var promise = new Promise(resolve => {
+ performance.clearMarks();
+ performance.clearMeasures();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe({entryTypes: ['mark', 'measure']});
+ observer.observe({entryTypes: ['mark', 'measure']});
+ t.add_cleanup(() => observer.disconnect());
+ });
+
+ performance.mark("test-start");
+ performance.mark("test-end");
+ performance.measure("test-measure", "test-start", "test-end");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 3,
+ "Observed user timing entries should have only three entries.");
+ });
+}, "Test that invoking observe method twice affects nothing");
+
+promise_test(t => {
+ var promise = new Promise(resolve => {
+ performance.clearMarks();
+ performance.clearMeasures();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe({entryTypes: ['mark', 'measure']});
+ observer.observe({entryTypes: ['mark']});
+ t.add_cleanup(() => observer.disconnect());
+ });
+
+ performance.mark("test-start");
+ performance.mark("test-end");
+ performance.measure("test-measure", "test-start", "test-end");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 2,
+ "Observed user timing entries should have only two entries.");
+ });
+}, "Test that observing filter is replaced by a new filter");
+
+promise_test(t => {
+ var promise = new Promise(resolve => {
+ performance.clearMarks();
+ performance.clearMeasures();
+
+ var observer = new PerformanceObserver(list => resolve(list));
+ observer.observe({entryTypes: ['mark']});
+ observer.observe({entryTypes: ['measure']});
+ t.add_cleanup(() => observer.disconnect());
+ });
+
+ performance.mark("test-start");
+ performance.mark("test-end");
+ performance.measure("test-measure", "test-start", "test-end");
+
+ return promise.then(list => {
+ assert_equals(list.getEntries().length, 1,
+ "Observed user timing entries should have only 1 entries.");
+ });
+}, "Test that observing filter is replaced by a new filter");
diff --git a/dom/performance/tests/test_performance_user_timing.html b/dom/performance/tests/test_performance_user_timing.html
new file mode 100644
index 000000000..5f4123eae
--- /dev/null
+++ b/dom/performance/tests/test_performance_user_timing.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=782751
+ -->
+ <head>
+ <title>Test for Bug 782751</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="test_performance_user_timing.js"></script>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=782751">Mozilla Bug 782751 - User Timing API</a>
+ <div id="content">
+ </div>
+ <pre id="test">
+ <script class="testbody" type="text/javascript">
+ var index = 0;
+
+ function next() {
+ ok(true, "Begin!");
+ var arr;
+ for (var i = 0; i < steps.length; ++i) {
+ try {
+ performance.clearMarks();
+ performance.clearMeasures();
+ performance.clearResourceTimings();
+ is(performance.getEntriesByType("resource").length, 0, "clearing performance resource entries");
+ is(performance.getEntriesByType("mark").length, 0, "clearing performance mark entries");
+ is(performance.getEntriesByType("measure").length, 0, "clearing performance measure entries");
+ steps[i]();
+ } catch(ex) {
+ ok(false, "Caught exception", ex);
+ }
+ }
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(next);
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/performance/tests/test_performance_user_timing.js b/dom/performance/tests/test_performance_user_timing.js
new file mode 100644
index 000000000..3d05ebb77
--- /dev/null
+++ b/dom/performance/tests/test_performance_user_timing.js
@@ -0,0 +1,272 @@
+var steps = [
+ // Test single mark addition
+ function () {
+ ok(true, "Running mark addition test");
+ performance.mark("test");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "Number of marks should be 1");
+ var mark = marks[0];
+ is(mark.name, "test", "mark name should be 'test'");
+ is(mark.entryType, "mark", "mark type should be 'mark'");
+ isnot(mark.startTime, 0, "mark start time should not be 0");
+ is(mark.duration, 0, "mark duration should be 0");
+ },
+ // Test multiple mark addition
+ function () {
+ ok(true, "Running multiple mark with same name addition test");
+ performance.mark("test");
+ performance.mark("test");
+ performance.mark("test");
+ var marks_type = performance.getEntriesByType("mark");
+ is(marks_type.length, 3, "Number of marks by type should be 3");
+ var marks_name = performance.getEntriesByName("test");
+ is(marks_name.length, 3, "Number of marks by name should be 3");
+ var mark = marks_name[0];
+ is(mark.name, "test", "mark name should be 'test'");
+ is(mark.entryType, "mark", "mark type should be 'mark'");
+ isnot(mark.startTime, 0, "mark start time should not be 0");
+ is(mark.duration, 0, "mark duration should be 0");
+ var times = [];
+ // This also tests the chronological ordering specified as
+ // required for getEntries in the performance timeline spec.
+ marks_name.forEach(function(s) {
+ times.forEach(function(time) {
+ ok(s.startTime >= time.startTime,
+ "Times should be equal or increasing between similarly named marks: " + s.startTime + " >= " + time.startTime);
+ });
+ times.push(s);
+ });
+ },
+ // Test all marks removal
+ function () {
+ ok(true, "Running all mark removal test");
+ performance.mark("test");
+ performance.mark("test2");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 2, "number of marks before all removal");
+ performance.clearMarks();
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 0, "number of marks after all removal");
+ },
+ // Test single mark removal
+ function () {
+ ok(true, "Running removal test (0 'test' marks with other marks)");
+ performance.mark("test2");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "number of marks after all removal");
+ },
+ // Test single mark removal
+ function () {
+ ok(true, "Running removal test (0 'test' marks with no other marks)");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 0, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 0, "number of marks after all removal");
+ },
+ function () {
+ ok(true, "Running removal test (1 'test' mark with other marks)");
+ performance.mark("test");
+ performance.mark("test2");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 2, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "number of marks after all removal");
+ },
+ function () {
+ ok(true, "Running removal test (1 'test' mark with no other marks)");
+ performance.mark("test");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 0, "number of marks after all removal");
+ },
+ function () {
+ ok(true, "Running removal test (2 'test' marks with other marks)");
+ performance.mark("test");
+ performance.mark("test");
+ performance.mark("test2");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 3, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 1, "number of marks after all removal");
+ },
+ function () {
+ ok(true, "Running removal test (2 'test' marks with no other marks)");
+ performance.mark("test");
+ performance.mark("test");
+ var marks = performance.getEntriesByType("mark");
+ is(marks.length, 2, "number of marks before all removal");
+ performance.clearMarks("test");
+ marks = performance.getEntriesByType("mark");
+ is(marks.length, 0, "number of marks after all removal");
+ },
+ // Test mark name being same as navigation timing parameter
+ function () {
+ ok(true, "Running mark name collision test");
+ for (n in performance.timing) {
+ try {
+ if (n == "toJSON") {
+ ok(true, "Skipping toJSON entry in collision test");
+ continue;
+ }
+ performance.mark(n);
+ ok(false, "Mark name collision test failed for name " + n + ", shouldn't make it here!");
+ } catch (e) {
+ ok(e instanceof DOMException, "DOM exception thrown for mark named " + n);
+ is(e.code, e.SYNTAX_ERR, "DOM exception for name collision is syntax error");
+ }
+ };
+ },
+ // Test measure
+ function () {
+ ok(true, "Running measure addition with no start/end time test");
+ performance.measure("test");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 1, "number of measures should be 1");
+ var measure = measures[0];
+ is(measure.name, "test", "measure name should be 'test'");
+ is(measure.entryType, "measure", "measure type should be 'measure'");
+ is(measure.startTime, 0, "measure start time should be zero");
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ },
+ function () {
+ ok(true, "Running measure addition with only start time test");
+ performance.mark("test1");
+ performance.measure("test", "test1", undefined);
+ var measures = performance.getEntriesByName("test", "measure");
+ var marks = performance.getEntriesByName("test1", "mark");
+ var measure = measures[0];
+ var mark = marks[0];
+ is(measure.startTime, mark.startTime, "measure start time should be equal to the mark startTime");
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ },
+ function () {
+ ok(true, "Running measure addition with only end time test");
+ performance.mark("test1");
+ performance.measure("test", undefined, "test1");
+ var measures = performance.getEntriesByName("test", "measure");
+ var marks = performance.getEntriesByName("test1", "mark");
+ var measure = measures[0];
+ var mark = marks[0];
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ },
+ // Test measure picking latest version of similarly named tags
+ function () {
+ ok(true, "Running multiple mark with same name addition test");
+ performance.mark("test");
+ performance.mark("test");
+ performance.mark("test");
+ performance.mark("test2");
+ var marks_name = performance.getEntriesByName("test");
+ is(marks_name.length, 3, "Number of marks by name should be 3");
+ var marks_name2 = performance.getEntriesByName("test2");
+ is(marks_name2.length, 1, "Number of marks by name should be 1");
+ var test_mark = marks_name2[0];
+ performance.measure("test", "test", "test2");
+ var measures_type = performance.getEntriesByType("measure");
+ var last_mark = marks_name[marks_name.length - 1];
+ is(measures_type.length, 1, "Number of measures by type should be 1");
+ var measure = measures_type[0];
+ is(measure.startTime, last_mark.startTime, "Measure start time should be the start time of the latest 'test' mark");
+ // Tolerance testing to avoid oranges, since we're doing double math across two different languages.
+ ok(measure.duration - (test_mark.startTime - last_mark.startTime) < .00001,
+ "Measure duration ( " + measure.duration + ") should be difference between two marks");
+ },
+ function() {
+ ok(true, "Running measure addition with no start/end time test");
+ performance.measure("test", "navigationStart");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 1, "number of measures should be 1");
+ var measure = measures[0];
+ is(measure.name, "test", "measure name should be 'test'");
+ is(measure.entryType, "measure", "measure type should be 'measure'");
+ is(measure.startTime, 0, "measure start time should be zero");
+ ok(measure.duration >= 0, "measure duration should not be negative");
+ },
+ // Test all measure removal
+ function () {
+ ok(true, "Running all measure removal test");
+ performance.measure("test");
+ performance.measure("test2");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 2, "measure entries should be length 2");
+ performance.clearMeasures();
+ measures = performance.getEntriesByType("measure");
+ is(measures.length, 0, "measure entries should be length 0");
+ },
+ // Test single measure removal
+ function () {
+ ok(true, "Running all measure removal test");
+ performance.measure("test");
+ performance.measure("test2");
+ var measures = performance.getEntriesByType("measure");
+ is(measures.length, 2, "measure entries should be length 2");
+ performance.clearMeasures("test");
+ measures = performance.getEntriesByType("measure");
+ is(measures.length, 1, "measure entries should be length 1");
+ },
+ // Test measure with invalid start time mark name
+ function () {
+ ok(true, "Running measure invalid start test");
+ try {
+ performance.measure("test", "notamark");
+ ok(false, "invalid measure start time exception not thrown!");
+ } catch (e) {
+ ok(e instanceof DOMException, "DOM exception thrown for invalid measure");
+ is(e.code, e.SYNTAX_ERR, "DOM exception for invalid time is syntax error");
+ }
+ },
+ // Test measure with invalid end time mark name
+ function () {
+ ok(true, "Running measure invalid end test");
+ try {
+ performance.measure("test", undefined, "notamark");
+ ok(false, "invalid measure end time exception not thrown!");
+ } catch (e) {
+ ok(e instanceof DOMException, "DOM exception thrown for invalid measure");
+ is(e.code, e.SYNTAX_ERR, "DOM exception for invalid time is syntax error");
+ }
+ },
+ // Test measure name being same as navigation timing parameter
+ function () {
+ ok(true, "Running measure name collision test");
+ for (n in performance.timing) {
+ try {
+ if (n == "toJSON") {
+ ok(true, "Skipping toJSON entry in collision test");
+ continue;
+ }
+ performance.measure(n);
+ ok(false, "Measure name collision test failed for name " + n + ", shouldn't make it here!");
+ } catch (e) {
+ ok(e instanceof DOMException, "DOM exception thrown for measure named " + n);
+ is(e.code, e.SYNTAX_ERR, "DOM exception for name collision is syntax error");
+ }
+ };
+ },
+ // Test measure mark being a reserved name
+ function () {
+ ok(true, "Create measures using all reserved names");
+ for (n in performance.timing) {
+ try {
+ if (n == "toJSON") {
+ ok(true, "Skipping toJSON entry in collision test");
+ continue;
+ }
+ performance.measure("test", n);
+ ok(true, "Measure created from reserved name as starting time: " + n);
+ } catch (e) {
+ ok(["redirectStart", "redirectEnd", "unloadEventStart", "unloadEventEnd", "loadEventEnd"].indexOf(n) >= 0,
+ "Measure created from reserved name as starting time: " + n + " and threw expected error");
+ }
+ };
+ },
+ // TODO: Test measure picking latest version of similarly named tags
+];
diff --git a/dom/performance/tests/test_sharedWorker_performance_user_timing.html b/dom/performance/tests/test_sharedWorker_performance_user_timing.html
new file mode 100644
index 000000000..0498672f3
--- /dev/null
+++ b/dom/performance/tests/test_sharedWorker_performance_user_timing.html
@@ -0,0 +1,27 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for worker performance timing API</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ </head>
+ <body>
+ <script class="testbody" type="text/javascript">
+
+var sw = new SharedWorker('sharedworker_performance_user_timing.js');
+sw.port.onmessage = function(event) {
+ if (event.data.type == 'finish') {
+ SimpleTest.finish();
+ } else if (event.data.type == 'status') {
+ ok(event.data.status, event.data.msg);
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+ </script>
+ </body>
+</html>
diff --git a/dom/performance/tests/test_worker_observer.html b/dom/performance/tests/test_worker_observer.html
new file mode 100644
index 000000000..b9ed0c964
--- /dev/null
+++ b/dom/performance/tests/test_worker_observer.html
@@ -0,0 +1,17 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for performance observer in worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+'use strict';
+SpecialPowers.pushPrefEnv({"set": [["dom.enable_performance_observer", true]]},
+ function() {
+ window.open("worker_performance_observer.html");
+ });
+</script>
diff --git a/dom/performance/tests/test_worker_performance_now.html b/dom/performance/tests/test_worker_performance_now.html
new file mode 100644
index 000000000..ec84ccd10
--- /dev/null
+++ b/dom/performance/tests/test_worker_performance_now.html
@@ -0,0 +1,32 @@
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Validate Interfaces Exposed to Workers</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+var worker = new Worker('test_worker_performance_now.js');
+worker.onmessage = function(event) {
+ if (event.data.type == 'finish') {
+ SimpleTest.finish();
+
+ } else if (event.data.type == 'status') {
+ ok(event.data.status, event.data.msg);
+
+ } else if (event.data.type == 'getOSCPU') {
+ worker.postMessage({
+ type: 'returnOSCPU',
+ result: navigator.oscpu
+ });
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/performance/tests/test_worker_performance_now.js b/dom/performance/tests/test_worker_performance_now.js
new file mode 100644
index 000000000..c2a905031
--- /dev/null
+++ b/dom/performance/tests/test_worker_performance_now.js
@@ -0,0 +1,76 @@
+function ok(a, msg) {
+ dump("OK: " + !!a + " => " + a + ": " + msg + "\n");
+ postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
+}
+
+function workerTestDone() {
+ postMessage({ type: 'finish' });
+}
+
+function workerTestGetOSCPU(cb) {
+ addEventListener('message', function workerTestGetOSCPUCB(e) {
+ if (e.data.type !== 'returnOSCPU') {
+ return;
+ }
+ removeEventListener('message', workerTestGetOSCPUCB);
+ cb(e.data.result);
+ });
+ postMessage({
+ type: 'getOSCPU'
+ });
+}
+
+ok(self.performance, "Performance object should exist.");
+ok(typeof self.performance.now == 'function', "Performance object should have a 'now' method.");
+var n = self.performance.now(), d = Date.now();
+ok(n >= 0, "The value of now() should be equal to or greater than 0.");
+ok(self.performance.now() >= n, "The value of now() should monotonically increase.");
+
+// The spec says performance.now() should have micro-second resolution, but allows 1ms if the platform doesn't support it.
+// Our implementation does provide micro-second resolution, except for windows XP combined with some HW properties
+// where we can't use QueryPerformanceCounters (see comments at mozilla-central/xpcom/ds/TimeStamp_windows.cpp).
+// This XP-low-res case results in about 15ms resolutions, and can be identified when perf.now() returns only integers.
+//
+// Since setTimeout might return too early/late, our goal is that perf.now() changed within 2ms
+// (or 25ms for XP-low-res), rather than specific number of setTimeout(N) invocations.
+// See bug 749894 (intermittent failures of this test)
+var platformPossiblyLowRes;
+workerTestGetOSCPU(function(oscpu) {
+ platformPossiblyLowRes = oscpu.indexOf("Windows NT 5.1") == 0; // XP only
+ setTimeout(checkAfterTimeout, 1);
+});
+var allInts = (n % 1) == 0; // Indicator of limited HW resolution.
+var checks = 0;
+
+function checkAfterTimeout() {
+ checks++;
+ var d2 = Date.now();
+ var n2 = self.performance.now();
+
+ allInts = allInts && (n2 % 1) == 0;
+ var lowResCounter = platformPossiblyLowRes && allInts;
+
+ if ( n2 == n && checks < 50 && // 50 is just a failsafe. Our real goals are 2ms or 25ms.
+ ( (d2 - d) < 2 // The spec allows 1ms resolution. We allow up to measured 2ms to ellapse.
+ ||
+ lowResCounter &&
+ (d2 - d) < 25
+ )
+ ) {
+ setTimeout(checkAfterTimeout, 1);
+ return;
+ }
+
+ // Loose spec: 1ms resolution, or 15ms resolution for the XP-low-res case.
+ // We shouldn't test that dt is actually within 2/25ms since the iterations break if it isn't, and timeout could be late.
+ ok(n2 > n, "Loose - the value of now() should increase within 2ms (or 25ms if low-res counter) (delta now(): " + (n2 - n) + " ms).");
+
+ // Strict spec: if it's not the XP-low-res case, while the spec allows 1ms resolution, it prefers microseconds, which we provide.
+ // Since the fastest setTimeout return which I observed was ~500 microseconds, a microseconds counter should change in 1 iteretion.
+ ok(n2 > n && (lowResCounter || checks == 1),
+ "Strict - [if high-res counter] the value of now() should increase after one setTimeout (hi-res: " + (!lowResCounter) +
+ ", iters: " + checks +
+ ", dt: " + (d2 - d) +
+ ", now(): " + n2 + ").");
+ workerTestDone();
+};
diff --git a/dom/performance/tests/test_worker_user_timing.html b/dom/performance/tests/test_worker_user_timing.html
new file mode 100644
index 000000000..2bf465cbd
--- /dev/null
+++ b/dom/performance/tests/test_worker_user_timing.html
@@ -0,0 +1,27 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Test for worker performance timing API</title>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ </head>
+ <body>
+ <script class="testbody" type="text/javascript">
+
+var worker = new Worker('worker_performance_user_timing.js');
+worker.onmessage = function(event) {
+ if (event.data.type == 'finish') {
+ SimpleTest.finish();
+ } else if (event.data.type == 'status') {
+ ok(event.data.status, event.data.msg);
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+ </script>
+ </body>
+</html>
diff --git a/dom/performance/tests/worker_performance_observer.html b/dom/performance/tests/worker_performance_observer.html
new file mode 100644
index 000000000..613762f52
--- /dev/null
+++ b/dom/performance/tests/worker_performance_observer.html
@@ -0,0 +1,32 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<meta charset=utf-8>
+<html>
+<head>
+<title>Test for performance observer in worker</title>
+</head>
+<body>
+<div id="log"></div>
+<script>
+[
+ "async_test", "test", "setup",
+ "assert_true", "assert_equals", "assert_array_equals",
+ "assert_throws", "fetch_tests_from_worker"
+].forEach(func => {
+ window[func] = opener[func].bind(opener);
+});
+
+function done() {
+ opener.add_completion_callback(() => {
+ self.close();
+ });
+ opener.done();
+}
+
+fetch_tests_from_worker(new Worker("worker_performance_observer.js"));
+done();
+</script>
+</body>
diff --git a/dom/performance/tests/worker_performance_observer.js b/dom/performance/tests/worker_performance_observer.js
new file mode 100644
index 000000000..8faf66f67
--- /dev/null
+++ b/dom/performance/tests/worker_performance_observer.js
@@ -0,0 +1,4 @@
+importScripts(['/resources/testharness.js']);
+importScripts(['test_performance_observer.js']);
+
+done();
diff --git a/dom/performance/tests/worker_performance_user_timing.js b/dom/performance/tests/worker_performance_user_timing.js
new file mode 100644
index 000000000..fa2f1afab
--- /dev/null
+++ b/dom/performance/tests/worker_performance_user_timing.js
@@ -0,0 +1,24 @@
+function ok(a, msg) {
+ dump("OK: " + !!a + " => " + a + " " + msg + "\n");
+ postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+ dump("IS: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
+ postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
+}
+
+function isnot(a, b, msg) {
+ dump("ISNOT: " + (a===b) + " => " + a + " | " + b + " " + msg + "\n");
+ postMessage({type: 'status', status: a != b, msg: a + " != " + b + ": " + msg });
+}
+
+importScripts(['test_performance_user_timing.js']);
+
+for (var i = 0; i < steps.length; ++i) {
+ performance.clearMarks();
+ performance.clearMeasures();
+ steps[i]();
+}
+
+postMessage({type: 'finish'});