'use strict'; // Dependencies: // * /common/utils.js // * /common/dispatcher/dispatcher.js // // This file contains the required infrastructure to run Compute Pressure tests // in both window and worker scopes transparently. // // We cannot just use the '.any.js' mechanism with "META: global=window,etc" // because we need the worker needs to manipulate virtual pressure sources, and // we can only do that by posting a message to the embedder window to do it due // to testdriver's limitations and operation model. // // See README.md for how to use pressure_test() and other functions within this // file. // // Example: // - /compute-pressure/foo.https.window.js // // META: variant=?globalScope=window // // META: variant=?globalScope=dedicated_worker // // META: script=/resources/testdriver.js // // META: script=/resources/testdriver-vendor.js // // META: script=/common/utils.js // // META: script=/common/dispatcher/dispatcher.js // // META: script=./resources/common.js // // pressure_test(async t => { // await create_virtual_pressure_source("cpu"); // t.add_cleanup(async () => { // await remove_virtual_pressure_source("cpu") // }); // /* rest of the test */ // }, "my test"); // // pressure_test(async t => { /* ... */ }); // // mark_as_done(); class WindowHelper { constructor() { setup({explicit_done: true}); // These are the calls made by tests that use pressure_test(). We do not // invoke the actual virtual pressure functions directly because of // compatibility with the dedicated workers case, where these calls are // done via postMessage (see resources/worker-support.js). globalThis.create_virtual_pressure_source = test_driver.create_virtual_pressure_source.bind(test_driver); globalThis.remove_virtual_pressure_source = test_driver.remove_virtual_pressure_source.bind(test_driver); globalThis.update_virtual_pressure_source = test_driver.update_virtual_pressure_source.bind(test_driver); } mark_as_done() { done(); } pressure_test(test_func, description) { promise_test(test_func, description); } } class DedicatedWorkerHelper { constructor() { this.token = token(); this.worker = new Worker( `/compute-pressure/resources/worker-support.js?uuid=${this.token}`); this.worker.onmessage = async (e) => { if (!e.data.command) { return; } switch (e.data.command) { case 'create': await test_driver.create_virtual_pressure_source(...e.data.params); break; case 'remove': await test_driver.remove_virtual_pressure_source(...e.data.params); break; case 'update': await test_driver.update_virtual_pressure_source(...e.data.params); break; default: throw new Error(`Unexpected command '${e.data.command}'`); } this.worker.postMessage({ command: e.data.command, id: e.data.id, }); }; // We need to call this here so that the testharness RemoteContext // infrastructure is set up before pressure_test() is called, as each test // will be added after the worker scaffolding code has loaded. this.fetch_tests_promise = fetch_tests_from_worker(this.worker); this.ctx = new RemoteContext(this.token); this.pending_tests = []; } async mark_as_done() { await Promise.all(this.pending_tests); await this.ctx.execute_script(() => { done(); }); await this.fetch_tests_from_worker; } async pressure_test(test_func, description) { this.pending_tests.push(this.ctx.execute_script( ` (description) => promise_test(${test_func}, description); `, [description])); } } let _pressureTestHelper; const _globalScope = new URLSearchParams(location.search).get('globalScope'); switch (_globalScope) { case 'window': _pressureTestHelper = new WindowHelper(); break; case 'dedicated_worker': _pressureTestHelper = new DedicatedWorkerHelper(); break; default: throw new Error(`Invalid variant '${_globalScope}'`); } promise_setup(async () => { // Ensure window's document has focus so that the global under test can // receive data. await test_driver.click(document.documentElement); }); const pressure_test = _pressureTestHelper.pressure_test.bind(_pressureTestHelper); const mark_as_done = _pressureTestHelper.mark_as_done.bind(_pressureTestHelper);