summaryrefslogtreecommitdiffstats
path: root/devtools/client/memory/test/xpcshell/head.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/memory/test/xpcshell/head.js')
-rw-r--r--devtools/client/memory/test/xpcshell/head.js189
1 files changed, 189 insertions, 0 deletions
diff --git a/devtools/client/memory/test/xpcshell/head.js b/devtools/client/memory/test/xpcshell/head.js
new file mode 100644
index 0000000000..94788a60fb
--- /dev/null
+++ b/devtools/client/memory/test/xpcshell/head.js
@@ -0,0 +1,189 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// via xpcshell.ini
+/* import-globals-from ../../../shared/test/shared-head.js */
+
+Services.prefs.setBoolPref("devtools.testing", true);
+Services.prefs.setBoolPref("devtools.debugger.log", true);
+registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("devtools.testing");
+ Services.prefs.clearUserPref("devtools.debugger.log");
+});
+
+var { FileUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/FileUtils.sys.mjs"
+);
+var { expectState } = require("resource://devtools/server/actors/common.js");
+var HeapSnapshotFileUtils = require("resource://devtools/shared/heapsnapshot/HeapSnapshotFileUtils.js");
+var HeapAnalysesClient = require("resource://devtools/shared/heapsnapshot/HeapAnalysesClient.js");
+var { addDebuggerToGlobal } = ChromeUtils.importESModule(
+ "resource://gre/modules/jsdebugger.sys.mjs"
+);
+var Store = require("resource://devtools/client/memory/store.js");
+var { L10N } = require("resource://devtools/client/memory/utils.js");
+var SYSTEM_PRINCIPAL = Cc["@mozilla.org/systemprincipal;1"].createInstance(
+ Ci.nsIPrincipal
+);
+
+var EXPECTED_DTU_ASSERT_FAILURE_COUNT = 0;
+
+registerCleanupFunction(function () {
+ equal(
+ DevToolsUtils.assertionFailureCount,
+ EXPECTED_DTU_ASSERT_FAILURE_COUNT,
+ "Should have had the expected number of DevToolsUtils.assert() failures."
+ );
+});
+
+function dumpn(msg) {
+ dump(`MEMORY-TEST: ${msg}\n`);
+}
+
+function initDebugger() {
+ const global = new Cu.Sandbox(SYSTEM_PRINCIPAL, { freshZone: true });
+ addDebuggerToGlobal(global);
+ return new global.Debugger();
+}
+
+function StubbedMemoryFront() {
+ this.state = "detached";
+ this.dbg = initDebugger();
+}
+
+StubbedMemoryFront.prototype.attach = async function () {
+ this.state = "attached";
+};
+
+StubbedMemoryFront.prototype.detach = async function () {
+ this.state = "detached";
+};
+
+StubbedMemoryFront.prototype.saveHeapSnapshot = expectState(
+ "attached",
+ async function () {
+ return ChromeUtils.saveHeapSnapshot({ runtime: true });
+ },
+ "saveHeapSnapshot"
+);
+
+StubbedMemoryFront.prototype.startRecordingAllocations = expectState(
+ "attached",
+ async function () {}
+);
+
+StubbedMemoryFront.prototype.stopRecordingAllocations = expectState(
+ "attached",
+ async function () {}
+);
+
+function waitUntilSnapshotState(store, expected) {
+ const predicate = () => {
+ const snapshots = store.getState().snapshots;
+ info(snapshots.map(x => x.state));
+ return (
+ snapshots.length === expected.length &&
+ expected.every(
+ (state, i) => state === "*" || snapshots[i].state === state
+ )
+ );
+ };
+ info(`Waiting for snapshots to be of state: ${expected}`);
+ return waitUntilState(store, predicate);
+}
+
+function findReportLeafIndex(node, name = null) {
+ if (node.reportLeafIndex && (!name || node.name === name)) {
+ return node.reportLeafIndex;
+ }
+
+ if (node.children) {
+ for (const child of node.children) {
+ const found = findReportLeafIndex(child);
+ if (found) {
+ return found;
+ }
+ }
+ }
+
+ return null;
+}
+
+function waitUntilCensusState(store, getCensus, expected) {
+ const predicate = () => {
+ const snapshots = store.getState().snapshots;
+
+ info(
+ "Current census state:" +
+ snapshots.map(x => (getCensus(x) ? getCensus(x).state : null))
+ );
+
+ return (
+ snapshots.length === expected.length &&
+ expected.every((state, i) => {
+ const census = getCensus(snapshots[i]);
+ return (
+ state === "*" ||
+ (!census && !state) ||
+ (census && census.state === state)
+ );
+ })
+ );
+ };
+ info(`Waiting for snapshots' censuses to be of state: ${expected}`);
+ return waitUntilState(store, predicate);
+}
+
+async function createTempFile() {
+ const file = new FileUtils.File(
+ PathUtils.join(PathUtils.tempDir, "tmp.fxsnapshot")
+ );
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
+ const destPath = file.path;
+ const stat = await IOUtils.stat(destPath);
+ Assert.strictEqual(stat.size, 0, "new file is 0 bytes at start");
+ return destPath;
+}
+
+// This is a copy of the same method from shared-head.js as
+// xpcshell test aren't using shared-head.js
+/**
+ * Wait for a specific action type to be dispatched.
+ *
+ * If the action is async and defines a `status` property, this helper will wait
+ * for the status to reach either "error" or "done".
+ *
+ * @param {Object} store
+ * Redux store where the action should be dispatched.
+ * @param {String} actionType
+ * The actionType to wait for.
+ * @param {Number} repeat
+ * Optional, number of time the action is expected to be dispatched.
+ * Defaults to 1
+ * @return {Promise}
+ */
+function waitForDispatch(store, actionType, repeat = 1) {
+ let count = 0;
+ return new Promise(resolve => {
+ store.dispatch({
+ type: "@@service/waitUntil",
+ predicate: action => {
+ const isDone =
+ !action.status ||
+ action.status === "done" ||
+ action.status === "error";
+
+ if (action.type === actionType && isDone && ++count == repeat) {
+ return true;
+ }
+
+ return false;
+ },
+ run: (dispatch, getState, action) => {
+ resolve(action);
+ },
+ });
+ });
+}