Skip to content

Commit

Permalink
test: add performance-timeline Web platform tests
Browse files Browse the repository at this point in the history
  • Loading branch information
targos committed May 7, 2020
1 parent e454e9b commit c2ebe75
Show file tree
Hide file tree
Showing 34 changed files with 944 additions and 0 deletions.
1 change: 1 addition & 0 deletions test/fixtures/wpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Last update:
- interfaces: https://github.com/web-platform-tests/wpt/tree/712c9f275e/interfaces
- html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/0c3bed38df/html/webappapis/microtask-queuing
- html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/ddfe9c089b/html/webappapis/timers
- performance-timeline: https://github.com/web-platform-tests/wpt/tree/61ff187c8d/performance-timeline

[Web Platform Tests]: https://github.com/web-platform-tests/wpt
[`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md#git-node-wpt
4 changes: 4 additions & 0 deletions test/fixtures/wpt/performance-timeline/META.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spec: https://w3c.github.io/performance-timeline/
suggested_reviewers:
- plehegar
- igrigorik
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
async_test(t => {
performance.mark('foo');
t.step_timeout(() => {
// After a timeout, PerformanceObserver should still receive entry if using the buffered flag.
new PerformanceObserver(t.step_func_done(list => {
const entries = list.getEntries();
assert_equals(entries.length, 1, 'There should be 1 mark entry.');
assert_equals(entries[0].entryType, 'mark');
})).observe({type: 'mark', buffered: true});
}, 100);
}, 'PerformanceObserver with buffered flag sees entry after timeout');
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
async_test( t=> {
for (let i = 0; i < 50; i++)
performance.mark('foo' + i);
let marksCreated = 50;
let marksReceived = 0;
new PerformanceObserver(list => {
marksReceived += list.getEntries().length;
if (marksCreated < 100) {
performance.mark('bar' + marksCreated);
marksCreated++;
}
if (marksReceived == 100)
t.done();
}).observe({type: 'mark', buffered: true});
}, 'PerformanceObserver with buffered flag should see past and future entries.');
29 changes: 29 additions & 0 deletions test/fixtures/wpt/performance-timeline/case-sensitivity.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
test(function () {
assert_equals(typeof self.performance, "object");
assert_equals(typeof self.performance.getEntriesByType, "function");
var lowerList = self.performance.getEntriesByType("resource");
var upperList = self.performance.getEntriesByType("RESOURCE");
var mixedList = self.performance.getEntriesByType("ReSoUrCe");

assert_not_equals(lowerList.length, 0, "Resource entries exist");
assert_equals(upperList.length, 0, "getEntriesByType('RESOURCE').length");
assert_equals(mixedList.length, 0, "getEntriesByType('ReSoUrCe').length");

}, "getEntriesByType values are case sensitive");

test(function () {
assert_equals(typeof self.performance, "object");
assert_equals(typeof self.performance.getEntriesByName, "function");
var origin = self.location.protocol + "//" + self.location.host;
var location1 = origin.toUpperCase() + "/resources/testharness.js";
var location2 = self.location.protocol + "//"
+ self.location.host.toUpperCase() + "/resources/testharness.js";
var lowerList = self.performance.getEntriesByName(origin + "/resources/testharness.js");
var upperList = self.performance.getEntriesByName(location1);
var mixedList = self.performance.getEntriesByName(location2);

assert_equals(lowerList.length, 1, "Resource entry exist");
assert_equals(upperList.length, 0, "getEntriesByName('" + location1 + "').length");
assert_equals(mixedList.length, 0, "getEntriesByName('" + location2 + "').length");

}, "getEntriesByName values are case sensitive");
27 changes: 27 additions & 0 deletions test/fixtures/wpt/performance-timeline/get-invalid-entries.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!doctype html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
async_test(function(t) {
performance.mark('windowMark');
const worker = new Worker("resources/worker-invalid-entries.js");
worker.onmessage = function(event) {
assert_equals(event.data['invalid'], 0, 'The worker must have 0 invalid entries.');
assert_equals(event.data['mark'], 1, 'The worker must have 1 mark entry.');
assert_equals(event.data['measure'], 0, 'The worker must have 0 measure entries.');
assert_equals(performance.getEntriesByType('invalid').length, 0,
'The window must have 0 invalid entries.');
assert_equals(performance.getEntriesByType('mark').length, 1,
'The window must have 1 mark entry.');
assert_equals(performance.getEntriesByType('measure').length, 0,
'The window must have 0 measure entries.')
t.done();
}
}, 'Get invalid entries from worker and window.');
</script>
</body>
</html>
25 changes: 25 additions & 0 deletions test/fixtures/wpt/performance-timeline/idlharness.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// META: global=window,worker
// META: script=/resources/WebIDLParser.js
// META: script=/resources/idlharness.js

// https://w3c.github.io/performance-timeline/

'use strict';

idl_test(
['performance-timeline'],
['hr-time', 'dom'],
async idl_array => {
idl_array.add_objects({
Performance: ['performance'],
PerformanceObserver: ['observer'],
PerformanceObserverEntryList: ['entryList'],
});

self.entryList = await new Promise((resolve, reject) => {
self.observer = new PerformanceObserver(resolve);
observer.observe({ entryTypes: ['mark'] });
performance.mark('test');
});
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
promise_test(() => {
// The first promise waits for one buffered flag observer to receive 3 entries.
const promise1 = new Promise(resolve1 => {
let numObserved1 = 0;
new PerformanceObserver((entryList, obs) => {
// This buffered flag observer is constructed after a regular observer detects a mark.
new PerformanceObserver(list => {
numObserved1 += list.getEntries().length;
if (numObserved1 == 3)
resolve1();
}).observe({type: 'mark', buffered: true});
obs.disconnect();
}).observe({entryTypes: ['mark']});
performance.mark('foo');
});
// The second promise waits for another buffered flag observer to receive 3 entries.
const promise2 = new Promise(resolve2 => {
step_timeout(() => {
let numObserved2 = 0;
// This buffered flag observer is constructed after a delay of 100ms.
new PerformanceObserver(list => {
numObserved2 += list.getEntries().length;
if (numObserved2 == 3)
resolve2();
}).observe({type: 'mark', buffered: true});
}, 100);
performance.mark('bar');
});
performance.mark('meow');
// Pass if and only if both buffered observers received all 3 mark entries.
return Promise.all([promise1, promise2]);
}, 'Multiple PerformanceObservers with buffered flag see all entries');
10 changes: 10 additions & 0 deletions test/fixtures/wpt/performance-timeline/not-clonable.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!doctype html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const t = async_test("Test that a postMessage of a performance entry fails");
addEventListener("message", t.step_func_done(e => {
assert_equals(e.data, "PASS");
}));
</script>
<iframe src="resources/postmessage-entry.html"></iframe>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
async_test(t => {
performance.mark('foo');
// Use a timeout to ensure the remainder of the test runs after the entry is created.
t.step_timeout(() => {
// Observer with buffered flag set to false should not see entry.
new PerformanceObserver(() => {
assert_unreached('Should not have observed any entry!');
}).observe({type: 'mark', buffered: false});
// Use a timeout to give time to the observer.
t.step_timeout(t.step_func_done(() => {}), 100);
}, 0);
}, 'PerformanceObserver without buffered flag set to false cannot see past entries.');
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
test(() => {
performance.mark('markName');
performance.measure('measureName');

const entries = performance.getEntries();
const performanceEntryKeys = [
'name',
'entryType',
'startTime',
'duration'
];
for (let i = 0; i < entries.length; ++i) {
assert_equals(typeof(entries[i].toJSON), 'function');
const json = entries[i].toJSON();
assert_equals(typeof(json), 'object');
for (const key of performanceEntryKeys) {
assert_equals(json[key], entries[i][key],
`entries[${i}].toJSON().${key} should match entries[${i}].${key}`);
}
}
}, 'Test toJSON() in PerformanceEntry');
44 changes: 44 additions & 0 deletions test/fixtures/wpt/performance-timeline/performanceobservers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Compares a performance entry to a predefined one
// perfEntriesToCheck is an array of performance entries from the user agent
// expectedEntries is an array of performance entries minted by the test
function checkEntries(perfEntriesToCheck, expectedEntries) {
function findMatch(pe) {
// we match based on entryType and name
for (var i = expectedEntries.length - 1; i >= 0; i--) {
var ex = expectedEntries[i];
if (ex.entryType === pe.entryType && ex.name === pe.name) {
return ex;
}
}
return null;
}

assert_equals(perfEntriesToCheck.length, expectedEntries.length, "performance entries must match");

perfEntriesToCheck.forEach(function (pe1) {
assert_not_equals(findMatch(pe1), null, "Entry matches");
});
}

// Waits for performance.now to advance. Since precision reduction might
// cause it to return the same value across multiple calls.
function wait() {
var now = performance.now();
while (now === performance.now())
continue;
}

// Ensure the entries list is sorted by startTime.
function checkSorted(entries) {
assert_not_equals(entries.length, 0, "entries list must not be empty");
if (!entries.length)
return;

var sorted = false;
var lastStartTime = entries[0].startTime;
for (var i = 1; i < entries.length; ++i) {
var currStartTime = entries[i].startTime;
assert_less_than_equal(lastStartTime, currStartTime, "entry list must be sorted by startTime");
lastStartTime = currStartTime;
}
}
66 changes: 66 additions & 0 deletions test/fixtures/wpt/performance-timeline/po-callback-mutate.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// META: script=performanceobservers.js

async_test(function (t) {
var callbackCount = 0;
var observer = new PerformanceObserver(
t.step_func(function (entryList, obs) {
callbackCount++;

if (callbackCount === 1) {
checkEntries(entryList.getEntries(), [
{entryType: "measure", name: "measure1"},
]);
observer.observe({entryTypes: ["mark"]});
self.performance.mark("mark2");
self.performance.measure("measure2");
return;
}

if (callbackCount === 2) {
checkEntries(entryList.getEntries(), [
{entryType: "mark", name: "mark2"},
]);
self.performance.mark("mark-before-change-observe-state-to-measure");
self.performance.measure("measure-before-change-observe-state-to-measure");
observer.observe({entryTypes: ["measure"]});
self.performance.mark("mark3");
self.performance.measure("measure3");
return;
}

if (callbackCount === 3) {
checkEntries(entryList.getEntries(), [
{entryType: "measure", name: "measure3"},
{entryType: "mark", name: "mark-before-change-observe-state-to-measure"},
]);
self.performance.mark("mark-before-change-observe-state-to-both");
self.performance.measure("measure-before-change-observe-state-to-both");
observer.observe({entryTypes: ["mark", "measure"]});
self.performance.mark("mark4");
self.performance.measure("measure4");
return;
}

if (callbackCount === 4) {
checkEntries(entryList.getEntries(), [
{entryType: "measure", name: "measure-before-change-observe-state-to-both"},
{entryType: "measure", name: "measure4"},
{entryType: "mark", name: "mark4"},
]);
self.performance.mark("mark-before-disconnect");
self.performance.measure("measure-before-disconnect");
observer.disconnect();
self.performance.mark("mark-after-disconnect");
self.performance.measure("measure-after-disconnect");
t.done();
return;
}

assert_unreached("The callback must not be invoked after disconnecting");
})
);

observer.observe({entryTypes: ["measure"]});
self.performance.mark("mark1");
self.performance.measure("measure1");
}, "PerformanceObserver modifications inside callback should update filtering and not clear buffer");
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// META: script=performanceobservers.js

async_test(function (t) {
const observer = new PerformanceObserver(
t.step_func(function (entryList) {
// There should be no mark entry.
checkEntries(entryList.getEntries(),
[{ entryType: "measure", name: "b"}]);
t.done();
})
);
observer.observe({type: "mark"});
// Disconnect the observer.
observer.disconnect();
// Now, only observe measure.
observer.observe({type: "measure"});
performance.mark("a");
performance.measure("b");
}, "Types observed are forgotten when disconnect() is called.");
37 changes: 37 additions & 0 deletions test/fixtures/wpt/performance-timeline/po-disconnect.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// META: script=performanceobservers.js

async_test(function (t) {
var observer = new PerformanceObserver(
t.step_func(function (entryList, obs) {
assert_unreached("This callback must not be invoked");
})
);
observer.observe({entryTypes: ["mark", "measure", "navigation"]});
observer.disconnect();
self.performance.mark("mark1");
self.performance.measure("measure1");
t.step_timeout(function () {
t.done();
}, 2000);
}, "disconnected callbacks must not be invoked");

test(function () {
var obs = new PerformanceObserver(function () { return true; });
obs.disconnect();
obs.disconnect();
}, "disconnecting an unconnected observer is a no-op");

async_test(function (t) {
var observer = new PerformanceObserver(
t.step_func(function (entryList, obs) {
assert_unreached("This callback must not be invoked");
})
);
observer.observe({entryTypes: ["mark"]});
self.performance.mark("mark1");
observer.disconnect();
self.performance.mark("mark2");
t.step_timeout(function () {
t.done();
}, 2000);
}, "An observer disconnected after a mark must not have its callback invoked");
Loading

0 comments on commit c2ebe75

Please sign in to comment.