tor-browser

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

head.js (7198B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // Load the shared test helpers into this compartment.
      7 Services.scriptloader.loadSubScript(
      8  "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
      9  this
     10 );
     11 
     12 var {
     13  censusDisplays,
     14  censusState,
     15  snapshotState: states,
     16 } = require("resource://devtools/client/memory/constants.js");
     17 var { L10N } = require("resource://devtools/client/memory/utils.js");
     18 
     19 Services.prefs.setBoolPref("devtools.memory.enabled", true);
     20 
     21 /**
     22 * Open the memory panel for the given tab.
     23 */
     24 this.openMemoryPanel = async function (tab) {
     25  info("Opening memory panel.");
     26  const toolbox = await gDevTools.showToolboxForTab(tab, { toolId: "memory" });
     27  info("Memory panel shown successfully.");
     28  const panel = toolbox.getCurrentPanel();
     29  return { tab, panel };
     30 };
     31 
     32 /**
     33 * Close the memory panel for the given tab.
     34 */
     35 this.closeMemoryPanel = async function (tab) {
     36  info("Closing memory panel.");
     37  const toolbox = gDevTools.getToolboxForTab(tab);
     38  await toolbox.destroy();
     39  info("Closed memory panel successfully.");
     40 };
     41 
     42 /**
     43 * Return a test function that adds a tab with the given url, opens the memory
     44 * panel, runs the given generator, closes the memory panel, removes the tab,
     45 * and finishes.
     46 *
     47 * Example usage:
     48 *
     49 *     this.test = makeMemoryTest(TEST_URL, async function ({ tab, panel }) {
     50 *         // Your tests go here...
     51 *     });
     52 */
     53 function makeMemoryTest(url, generator) {
     54  return async function () {
     55    waitForExplicitFinish();
     56 
     57    // It can take a long time to save a snapshot to disk, read the snapshots
     58    // back from disk, and finally perform analyses on them.
     59    requestLongerTimeout(2);
     60 
     61    const tab = await addTab(url);
     62    const results = await openMemoryPanel(tab);
     63 
     64    try {
     65      await generator(results);
     66    } catch (err) {
     67      ok(false, "Got an error: " + DevToolsUtils.safeErrorString(err));
     68    }
     69 
     70    await closeMemoryPanel(tab);
     71    await removeTab(tab);
     72 
     73    finish();
     74  };
     75 }
     76 
     77 function dumpn(msg) {
     78  dump(`MEMORY-TEST: ${msg}\n`);
     79 }
     80 
     81 /**
     82 * Returns a promise that will resolve when the provided store matches
     83 * the expected array. expectedStates is an array of dominatorTree states.
     84 * Expectations :
     85 * - store.getState().snapshots.length == expected.length
     86 * - snapshots[i].dominatorTree.state == expected[i]
     87 *
     88 * @param  {Store} store
     89 * @param  {Array<string>} expectedStates [description]
     90 * @return {Promise}
     91 */
     92 function waitUntilDominatorTreeState(store, expected) {
     93  const predicate = () => {
     94    const snapshots = store.getState().snapshots;
     95    return (
     96      snapshots.length === expected.length &&
     97      expected.every((state, i) => {
     98        return (
     99          snapshots[i].dominatorTree &&
    100          snapshots[i].dominatorTree.state === state
    101        );
    102      })
    103    );
    104  };
    105  info(`Waiting for dominator trees to be of state: ${expected}`);
    106  return waitUntilState(store, predicate);
    107 }
    108 
    109 function takeSnapshot(window) {
    110  const { gStore, document } = window;
    111  const snapshotCount = gStore.getState().snapshots.length;
    112  info("Taking snapshot...");
    113  document.querySelector(".devtools-toolbar .take-snapshot").click();
    114  return waitUntilState(
    115    gStore,
    116    () => gStore.getState().snapshots.length === snapshotCount + 1
    117  );
    118 }
    119 
    120 function clearSnapshots(window) {
    121  const { gStore, document } = window;
    122  document.querySelector(".devtools-toolbar .clear-snapshots").click();
    123  return waitUntilState(gStore, () =>
    124    gStore
    125      .getState()
    126      .snapshots.every(snapshot => snapshot.state !== states.READ)
    127  );
    128 }
    129 
    130 /**
    131 * Sets the current requested display and waits for the selected snapshot to use
    132 * it and complete the new census that entails.
    133 */
    134 function setCensusDisplay(window, display) {
    135  info(`Setting census display to ${display}...`);
    136  const { gStore, gHeapAnalysesClient } = window;
    137  // XXX: Should handle this via clicking the DOM, but React doesn't
    138  // fire the onChange event, so just change it in the store.
    139  // window.document.querySelector(`.select-display`).value = type;
    140  gStore.dispatch(
    141    require("resource://devtools/client/memory/actions/census-display.js").setCensusDisplayAndRefresh(
    142      gHeapAnalysesClient,
    143      display
    144    )
    145  );
    146 
    147  return waitUntilState(window.gStore, () => {
    148    const selected = window.gStore.getState().snapshots.find(s => s.selected);
    149    return (
    150      selected.state === states.READ &&
    151      selected.census &&
    152      selected.census.state === censusState.SAVED &&
    153      selected.census.display === display
    154    );
    155  });
    156 }
    157 
    158 /**
    159 * Get the snapshot tatus text currently displayed, or null if none is
    160 * displayed.
    161 *
    162 * @param {Document} document
    163 */
    164 function getDisplayedSnapshotStatus(document) {
    165  const status = document.querySelector(".snapshot-status");
    166  return status ? status.textContent.trim() : null;
    167 }
    168 
    169 /**
    170 * Get the index of the currently selected snapshot.
    171 *
    172 * @return {number}
    173 */
    174 function getSelectedSnapshotIndex(store) {
    175  const snapshots = store.getState().snapshots;
    176  const selectedSnapshot = snapshots.find(s => s.selected);
    177  return snapshots.indexOf(selectedSnapshot);
    178 }
    179 
    180 /**
    181 * Returns a promise that will resolve when the snapshot with provided index
    182 * becomes selected.
    183 *
    184 * @return {Promise}
    185 */
    186 function waitUntilSnapshotSelected(store, snapshotIndex) {
    187  return waitUntilState(
    188    store,
    189    state =>
    190      state.snapshots[snapshotIndex] &&
    191      state.snapshots[snapshotIndex].selected === true
    192  );
    193 }
    194 
    195 /**
    196 * Wait until the state has censuses in a certain state.
    197 *
    198 * @return {Promise}
    199 */
    200 function waitUntilCensusState(store, getCensus, expected) {
    201  const predicate = () => {
    202    const snapshots = store.getState().snapshots;
    203 
    204    info(
    205      "Current census state:" +
    206        snapshots.map(x => (getCensus(x) ? getCensus(x).state : null))
    207    );
    208 
    209    return (
    210      snapshots.length === expected.length &&
    211      expected.every((state, i) => {
    212        const census = getCensus(snapshots[i]);
    213        return (
    214          state === "*" ||
    215          (!census && !state) ||
    216          (census && census.state === state)
    217        );
    218      })
    219    );
    220  };
    221  info(`Waiting for snapshot censuses to be of state: ${expected}`);
    222  return waitUntilState(store, predicate);
    223 }
    224 
    225 /**
    226 * Mock out the requestAnimationFrame.
    227 *
    228 * @return {object}
    229 * @function nextFrame
    230 *           Call the last queued function
    231 * @function raf
    232 *           The mocked raf function
    233 * @function timesCalled
    234 *           How many times the RAF has been called
    235 */
    236 function createRAFMock() {
    237  let queuedFns = [];
    238  const mock = { timesCalled: 0 };
    239 
    240  mock.nextFrame = function () {
    241    const thisQueue = queuedFns;
    242    queuedFns = [];
    243    for (let i = 0; i < thisQueue.length; i++) {
    244      thisQueue[i]();
    245    }
    246  };
    247 
    248  mock.raf = function (fn) {
    249    mock.timesCalled++;
    250    queuedFns.push(fn);
    251  };
    252  return mock;
    253 }
    254 
    255 /**
    256 * Test to see if two floats are equivalent.
    257 *
    258 * @param {Float} a
    259 * @param {Float} b
    260 * @return {boolean}
    261 */
    262 function floatEquality(a, b) {
    263  const EPSILON = 0.00000000001;
    264  const equals = Math.abs(a - b) < EPSILON;
    265  if (!equals) {
    266    info(`${a} not equal to ${b}`);
    267  }
    268  return equals;
    269 }