common.js (4499B)
1 'use strict'; 2 3 // Dependencies: 4 // * /common/utils.js 5 // * /common/dispatcher/dispatcher.js 6 // 7 // This file contains the required infrastructure to run Compute Pressure tests 8 // in both window and worker scopes transparently. 9 // 10 // We cannot just use the '.any.js' mechanism with "META: global=window,etc" 11 // because we need the worker needs to manipulate virtual pressure sources, and 12 // we can only do that by posting a message to the embedder window to do it due 13 // to testdriver's limitations and operation model. 14 // 15 // See README.md for how to use pressure_test() and other functions within this 16 // file. 17 // 18 // Example: 19 // - /compute-pressure/foo.https.window.js 20 // // META: variant=?globalScope=window 21 // // META: variant=?globalScope=dedicated_worker 22 // // META: script=/resources/testdriver.js 23 // // META: script=/resources/testdriver-vendor.js 24 // // META: script=/common/utils.js 25 // // META: script=/common/dispatcher/dispatcher.js 26 // // META: script=./resources/common.js 27 // 28 // pressure_test(async t => { 29 // await create_virtual_pressure_source("cpu"); 30 // t.add_cleanup(async () => { 31 // await remove_virtual_pressure_source("cpu") 32 // }); 33 // /* rest of the test */ 34 // }, "my test"); 35 // 36 // pressure_test(async t => { /* ... */ }); 37 // 38 // mark_as_done(); 39 40 class WindowHelper { 41 constructor() { 42 setup({explicit_done: true}); 43 44 // These are the calls made by tests that use pressure_test(). We do not 45 // invoke the actual virtual pressure functions directly because of 46 // compatibility with the dedicated workers case, where these calls are 47 // done via postMessage (see resources/worker-support.js). 48 globalThis.create_virtual_pressure_source = 49 test_driver.create_virtual_pressure_source.bind(test_driver); 50 globalThis.remove_virtual_pressure_source = 51 test_driver.remove_virtual_pressure_source.bind(test_driver); 52 globalThis.update_virtual_pressure_source = 53 test_driver.update_virtual_pressure_source.bind(test_driver); 54 } 55 56 mark_as_done() { 57 done(); 58 } 59 60 pressure_test(test_func, description) { 61 promise_test(test_func, description); 62 } 63 } 64 65 class DedicatedWorkerHelper { 66 constructor() { 67 this.token = token(); 68 69 this.worker = new Worker( 70 `/compute-pressure/resources/worker-support.js?uuid=${this.token}`); 71 this.worker.onmessage = async (e) => { 72 if (!e.data.command) { 73 return; 74 } 75 76 switch (e.data.command) { 77 case 'create': 78 await test_driver.create_virtual_pressure_source(...e.data.params); 79 break; 80 81 case 'remove': 82 await test_driver.remove_virtual_pressure_source(...e.data.params); 83 break; 84 85 case 'update': 86 await test_driver.update_virtual_pressure_source(...e.data.params); 87 break; 88 89 default: 90 throw new Error(`Unexpected command '${e.data.command}'`); 91 } 92 93 this.worker.postMessage({ 94 command: e.data.command, 95 id: e.data.id, 96 }); 97 }; 98 99 // We need to call this here so that the testharness RemoteContext 100 // infrastructure is set up before pressure_test() is called, as each test 101 // will be added after the worker scaffolding code has loaded. 102 this.fetch_tests_promise = fetch_tests_from_worker(this.worker); 103 104 this.ctx = new RemoteContext(this.token); 105 106 this.pending_tests = []; 107 } 108 109 async mark_as_done() { 110 await Promise.all(this.pending_tests); 111 await this.ctx.execute_script(() => { 112 done(); 113 }); 114 await this.fetch_tests_from_worker; 115 } 116 117 async pressure_test(test_func, description) { 118 this.pending_tests.push(this.ctx.execute_script( 119 ` 120 (description) => promise_test(${test_func}, description); 121 `, 122 [description])); 123 } 124 } 125 126 let _pressureTestHelper; 127 const _globalScope = new URLSearchParams(location.search).get('globalScope'); 128 switch (_globalScope) { 129 case 'window': 130 _pressureTestHelper = new WindowHelper(); 131 break; 132 case 'dedicated_worker': 133 _pressureTestHelper = new DedicatedWorkerHelper(); 134 break; 135 default: 136 throw new Error(`Invalid variant '${_globalScope}'`); 137 } 138 139 promise_setup(async () => { 140 // Ensure window's document has focus so that the global under test can 141 // receive data. 142 await test_driver.click(document.documentElement); 143 }); 144 145 const pressure_test = 146 _pressureTestHelper.pressure_test.bind(_pressureTestHelper); 147 const mark_as_done = _pressureTestHelper.mark_as_done.bind(_pressureTestHelper);