From cd92052935e19a9e684f12c5ec49dd9441d8fe5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 7 May 2020 20:49:56 +0200 Subject: [PATCH] test: add hr-time Web platform tests Refs: https://github.com/nodejs/node/pull/32790 PR-URL: https://github.com/nodejs/node/pull/33287 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- test/fixtures/wpt/README.md | 1 + test/fixtures/wpt/hr-time/META.yml | 4 + test/fixtures/wpt/hr-time/basic.any.js | 28 +++++++ test/fixtures/wpt/hr-time/idlharness.any.js | 23 ++++++ .../wpt/hr-time/monotonic-clock.any.js | 13 ++++ .../wpt/hr-time/performance-tojson.html | 76 +++++++++++++++++++ .../wpt/hr-time/resources/now_frame.html | 9 +++ .../wpt/hr-time/resources/unload-a.html | 13 ++++ .../wpt/hr-time/resources/unload-b.html | 13 ++++ .../wpt/hr-time/resources/unload-c.html | 13 ++++ test/fixtures/wpt/hr-time/resources/unload.js | 50 ++++++++++++ .../wpt/hr-time/test_cross_frame_start.html | 59 ++++++++++++++ test/fixtures/wpt/hr-time/timeOrigin.html | 45 +++++++++++ test/fixtures/wpt/hr-time/timing-attack.html | 55 ++++++++++++++ test/fixtures/wpt/hr-time/unload-manual.html | 73 ++++++++++++++++++ .../window-worker-timeOrigin.window.js | 30 ++++++++ test/fixtures/wpt/versions.json | 4 + test/wpt/status/hr-time.json | 1 + test/wpt/test-hr-time.js | 27 +++++++ 19 files changed, 537 insertions(+) create mode 100644 test/fixtures/wpt/hr-time/META.yml create mode 100644 test/fixtures/wpt/hr-time/basic.any.js create mode 100644 test/fixtures/wpt/hr-time/idlharness.any.js create mode 100644 test/fixtures/wpt/hr-time/monotonic-clock.any.js create mode 100644 test/fixtures/wpt/hr-time/performance-tojson.html create mode 100644 test/fixtures/wpt/hr-time/resources/now_frame.html create mode 100644 test/fixtures/wpt/hr-time/resources/unload-a.html create mode 100644 test/fixtures/wpt/hr-time/resources/unload-b.html create mode 100644 test/fixtures/wpt/hr-time/resources/unload-c.html create mode 100644 test/fixtures/wpt/hr-time/resources/unload.js create mode 100644 test/fixtures/wpt/hr-time/test_cross_frame_start.html create mode 100644 test/fixtures/wpt/hr-time/timeOrigin.html create mode 100644 test/fixtures/wpt/hr-time/timing-attack.html create mode 100644 test/fixtures/wpt/hr-time/unload-manual.html create mode 100644 test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js create mode 100644 test/wpt/status/hr-time.json create mode 100644 test/wpt/test-hr-time.js diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index dcf42abe7925f7..421b5fdcb77fc7 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -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 +- hr-time: https://github.com/web-platform-tests/wpt/tree/a5d1774ecf/hr-time [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 diff --git a/test/fixtures/wpt/hr-time/META.yml b/test/fixtures/wpt/hr-time/META.yml new file mode 100644 index 00000000000000..779d5b4af08428 --- /dev/null +++ b/test/fixtures/wpt/hr-time/META.yml @@ -0,0 +1,4 @@ +spec: https://w3c.github.io/hr-time/ +suggested_reviewers: + - plehegar + - igrigorik diff --git a/test/fixtures/wpt/hr-time/basic.any.js b/test/fixtures/wpt/hr-time/basic.any.js new file mode 100644 index 00000000000000..364dd81a344818 --- /dev/null +++ b/test/fixtures/wpt/hr-time/basic.any.js @@ -0,0 +1,28 @@ +test(function() { + assert_true((self.performance !== undefined), "self.performance exists"); + assert_equals(typeof self.performance, "object", "self.performance is an object"); + assert_equals((typeof self.performance.now), "function", "self.performance.now() is a function"); + assert_equals(typeof self.performance.now(), "number", "self.performance.now() returns a number"); +}, "self.performance.now() is a function that returns a number"); + +test(function() { + assert_true(self.performance.now() > 0); +}, "self.performance.now() returns a positive number"); + +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0); + }, "self.performance.now() difference is not negative"); + +async_test(function() { + // Check whether the performance.now() method is close to Date() within 30ms (due to inaccuracies) + var initial_hrt = self.performance.now(); + var initial_date = Date.now(); + this.step_timeout(function() { + var final_hrt = self.performance.now(); + var final_date = Date.now(); + assert_approx_equals(final_hrt - initial_hrt, final_date - initial_date, 30, 'High resolution time value increased by approximately the same amount as time from date object'); + this.done(); + }, 2000); +}, 'High resolution time has approximately the right relative magnitude'); diff --git a/test/fixtures/wpt/hr-time/idlharness.any.js b/test/fixtures/wpt/hr-time/idlharness.any.js new file mode 100644 index 00000000000000..6676b001a8b816 --- /dev/null +++ b/test/fixtures/wpt/hr-time/idlharness.any.js @@ -0,0 +1,23 @@ +// META: global=window,worker +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +// https://w3c.github.io/hr-time/ + +idl_test( + ['hr-time'], + ['html', 'dom'], + async idl_array => { + if (self.GLOBAL.isWorker()) { + idl_array.add_objects({ WorkerGlobalScope: ['self'] }); + } else { + idl_array.add_objects({ Window: ['self'] }); + } + idl_array.add_objects({ + Performance: ['performance'], + }); + } +); diff --git a/test/fixtures/wpt/hr-time/monotonic-clock.any.js b/test/fixtures/wpt/hr-time/monotonic-clock.any.js new file mode 100644 index 00000000000000..c53b04d844e4f5 --- /dev/null +++ b/test/fixtures/wpt/hr-time/monotonic-clock.any.js @@ -0,0 +1,13 @@ +// The time values returned when calling the now method MUST be monotonically increasing and not subject to system clock adjustments or system clock skew. +test(function() { + assert_true(self.performance.now() > 0, "self.performance.now() returns positive numbers"); +}, "self.performance.now() returns a positive number"); + +// The difference between any two chronologically recorded time values returned from the now method MUST never be negative. +test(function() { + var now1 = self.performance.now(); + var now2 = self.performance.now(); + assert_true((now2-now1) >= 0, "self.performance.now() difference is not negative"); + }, + "self.performance.now() difference is not negative" +); diff --git a/test/fixtures/wpt/hr-time/performance-tojson.html b/test/fixtures/wpt/hr-time/performance-tojson.html new file mode 100644 index 00000000000000..fd8049cb9a1eee --- /dev/null +++ b/test/fixtures/wpt/hr-time/performance-tojson.html @@ -0,0 +1,76 @@ + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/hr-time/resources/now_frame.html b/test/fixtures/wpt/hr-time/resources/now_frame.html new file mode 100644 index 00000000000000..5bec688af9cd3c --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/now_frame.html @@ -0,0 +1,9 @@ + + + + + window.performance.now frame + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-a.html b/test/fixtures/wpt/hr-time/resources/unload-a.html new file mode 100644 index 00000000000000..40c1d061830e6f --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-a.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-b.html b/test/fixtures/wpt/hr-time/resources/unload-b.html new file mode 100644 index 00000000000000..7c2d90df275fbc --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-b.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload-c.html b/test/fixtures/wpt/hr-time/resources/unload-c.html new file mode 100644 index 00000000000000..731da9db758ba5 --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload-c.html @@ -0,0 +1,13 @@ + + + + Helper page for ../unload-manual.html + + + + + + + diff --git a/test/fixtures/wpt/hr-time/resources/unload.js b/test/fixtures/wpt/hr-time/resources/unload.js new file mode 100644 index 00000000000000..06b0bc7da78b4b --- /dev/null +++ b/test/fixtures/wpt/hr-time/resources/unload.js @@ -0,0 +1,50 @@ +const syncDelay = ms => { + const start = performance.now(); + let elapsedTime; + do { + elapsedTime = performance.now() - start; + } while (elapsedTime < ms); +}; + +const markTime = (docName, lifecycleEventName) => { + // Calculating these values before the below `mark` invocation ensures that delays in + // reaching across to the other window object doesn't interfere with the correctness + // of the test. + const dateNow = Date.now(); + const performanceNow = performance.now(); + + window.opener.mark({ + docName, + lifecycleEventName, + performanceNow: performanceNow, + dateNow: dateNow + }); +}; + +const setupUnloadPrompt = (docName, msg) => { + window.addEventListener("beforeunload", ev => { + markTime(docName, "beforeunload"); + return ev.returnValue = msg || "Click OK to continue test." + }); +}; + +const setupListeners = (docName, nextDocument) => { + window.addEventListener("load", () => { + markTime(docName, "load"); + document.getElementById("proceed").addEventListener("click", ev => { + ev.preventDefault(); + if (nextDocument) { + document.location = nextDocument; + } else { + window.close(); + } + }) + }); + + setupUnloadPrompt(docName); + + window.addEventListener("unload", () => { + markTime(docName, "unload"); + if (docName !== "c") { syncDelay(1000); } + }); +}; diff --git a/test/fixtures/wpt/hr-time/test_cross_frame_start.html b/test/fixtures/wpt/hr-time/test_cross_frame_start.html new file mode 100644 index 00000000000000..30e804bd735031 --- /dev/null +++ b/test/fixtures/wpt/hr-time/test_cross_frame_start.html @@ -0,0 +1,59 @@ + + + + + window.performance.now across frames + + + + + + + + + + +

Description

+

This test validates the values of the window.performance.now() are based on the current document's navigationStart.

+
+ + diff --git a/test/fixtures/wpt/hr-time/timeOrigin.html b/test/fixtures/wpt/hr-time/timeOrigin.html new file mode 100644 index 00000000000000..20aea75084515a --- /dev/null +++ b/test/fixtures/wpt/hr-time/timeOrigin.html @@ -0,0 +1,45 @@ + + + + + + + + + + \ No newline at end of file diff --git a/test/fixtures/wpt/hr-time/timing-attack.html b/test/fixtures/wpt/hr-time/timing-attack.html new file mode 100644 index 00000000000000..71ade4a8c48ce2 --- /dev/null +++ b/test/fixtures/wpt/hr-time/timing-attack.html @@ -0,0 +1,55 @@ + + + + +window.performance.now should not enable timing attacks + + + + + + + +

Description

+

The recommended minimum resolution of the Performance interface should be set to 5 microseconds.

+ +
+ + + diff --git a/test/fixtures/wpt/hr-time/unload-manual.html b/test/fixtures/wpt/hr-time/unload-manual.html new file mode 100644 index 00000000000000..18c4e0dc327919 --- /dev/null +++ b/test/fixtures/wpt/hr-time/unload-manual.html @@ -0,0 +1,73 @@ + + + + time origin value manual test + + + + + + + + + + +

Description

+

This test validates the behavior of performance.now() with respect to its time origin.

+
+

Manual Test Steps

+
    +
  1. Click here +
+
+ + diff --git a/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js b/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js new file mode 100644 index 00000000000000..1e5ef1cdffecf6 --- /dev/null +++ b/test/fixtures/wpt/hr-time/window-worker-timeOrigin.window.js @@ -0,0 +1,30 @@ +"use strict" +// https://w3c.github.io/hr-time/#time-origin + +async_test(function(test) { + // Cache global time before starting worker + const globalTimeOrigin = performance.timeOrigin; + const globalNowBeforeWorkerStart = performance.now(); + + // Start worker and retrieve time + const workerScript = "postMessage({timeOrigin: performance.timeOrigin, now: performance.now()})"; + const blob = new Blob([workerScript]); + let worker = new Worker(URL.createObjectURL(blob)); + + worker.addEventListener("message", test.step_func_done(function(event) { + const workerTimeOrigin = event.data.timeOrigin; + const workerNow = event.data.now; + + assert_not_equals(workerTimeOrigin, 0, "worker timeOrigin must not be 0"); + assert_not_equals(performance.timeOrigin, 0, "Document timeOrigin must not be 0"); + + assert_equals(globalTimeOrigin, performance.timeOrigin, "timeOrigin should not be changed in same document mode"); + assert_less_than(globalTimeOrigin, workerTimeOrigin, "Document timeOrigin must be earlier than worker timeOrigin"); + + // Document and worker's now() start from their respective timeOrigins. + const timeDiff = workerTimeOrigin - globalTimeOrigin; // convert worker's time to Document time. + assert_less_than(globalTimeOrigin + globalNowBeforeWorkerStart, globalTimeOrigin + timeDiff + workerNow, "Document old now is earlier than worker now."); + + // Comparing timing between Document and worker threads could be delicate as it relies on the thread implementation and could be subject to race conditions. + })); +}, 'timeOrigin and now() should be correctly ordered between window and worker'); diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index c560f6844e9e3d..5fdc09c4f4f8c5 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -26,5 +26,9 @@ "html/webappapis/timers": { "commit": "ddfe9c089bab565a9d3aa37bdef63d8012c1a94c", "path": "html/webappapis/timers" + }, + "hr-time": { + "commit": "a5d1774ecf41751d1c9357c27c709ee33bf3e279", + "path": "hr-time" } } \ No newline at end of file diff --git a/test/wpt/status/hr-time.json b/test/wpt/status/hr-time.json new file mode 100644 index 00000000000000..0967ef424bce67 --- /dev/null +++ b/test/wpt/status/hr-time.json @@ -0,0 +1 @@ +{} diff --git a/test/wpt/test-hr-time.js b/test/wpt/test-hr-time.js new file mode 100644 index 00000000000000..eb9c68797dfcbf --- /dev/null +++ b/test/wpt/test-hr-time.js @@ -0,0 +1,27 @@ +'use strict'; + +// Flags: --expose-internals + +require('../common'); +const { WPTRunner } = require('../common/wpt'); +const { performance, PerformanceObserver } = require('perf_hooks'); + +const runner = new WPTRunner('hr-time'); + +runner.copyGlobalsFromObject(global, [ + 'setInterval', + 'clearInterval', + 'setTimeout', + 'clearTimeout' +]); + +runner.defineGlobal('performance', { + get() { + return performance; + } +}); +runner.defineGlobal('PerformanceObserver', { + value: PerformanceObserver +}); + +runner.runJsTests();