/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /* eslint-env mozilla/frame-script */ // Functions that are automatically loaded as frame scripts for // timeline tests. // eslint assumes we inherit browser window stuff, but this // framescript doesn't. // eslint-disable-next-line mozilla/no-redeclare-with-import-autofix const { setTimeout } = ChromeUtils.importESModule( "resource://gre/modules/Timer.sys.mjs" ); // Functions that look like mochitest functions but forward to the // browser process. this.ok = function (value, message) { sendAsyncMessage("browser:test:ok", { value: !!value, message, }); }; this.is = function (v1, v2, message) { ok(v1 == v2, message); }; this.info = function (message) { sendAsyncMessage("browser:test:info", { message }); }; this.finish = function () { sendAsyncMessage("browser:test:finish"); }; /* Start a task that runs some timeline tests in the ordinary way. * * @param array tests * The tests to run. This is an array where each element * is of the form { desc, searchFor, setup, check }. * * desc is the test description, a string. * searchFor is a string or a function * If a string, then when a marker with this name is * found, marker-reading is stopped. * If a function, then the accumulated marker array is * passed to it, and marker reading stops when it returns * true. * setup is a function that takes the docshell as an argument. * It should start the test. * check is a function that takes an array of markers * as an argument and checks the results of the test. */ this.timelineContentTest = function (tests) { (async function () { let docShell = content.docShell; info("Start recording"); docShell.recordProfileTimelineMarkers = true; for (let { desc, searchFor, setup, check } of tests) { info("Running test: " + desc); info("Flushing the previous markers if any"); docShell.popProfileTimelineMarkers(); info("Running the test setup function"); let onMarkers = timelineWaitForMarkers(docShell, searchFor); setup(docShell); info("Waiting for new markers on the docShell"); let markers = await onMarkers; // Cycle collection markers are non-deterministic, and none of these tests // expect them to show up. markers = markers.filter(m => !m.name.includes("nsCycleCollector")); info("Running the test check function"); check(markers); } info("Stop recording"); docShell.recordProfileTimelineMarkers = false; finish(); })(); }; function timelineWaitForMarkers(docshell, searchFor) { if (typeof searchFor == "string") { let searchForString = searchFor; let f = function (markers) { return markers.some(m => m.name == searchForString); }; searchFor = f; } return new Promise(function (resolve, reject) { let waitIterationCount = 0; let maxWaitIterationCount = 10; // Wait for 2sec maximum let markers = []; setTimeout(function timeoutHandler() { let newMarkers = docshell.popProfileTimelineMarkers(); markers = [...markers, ...newMarkers]; if (searchFor(markers) || waitIterationCount > maxWaitIterationCount) { resolve(markers); } else { setTimeout(timeoutHandler, 200); waitIterationCount++; } }, 200); }); }