tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);