summaryrefslogtreecommitdiffstats
path: root/toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js')
-rw-r--r--toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js b/toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js
new file mode 100644
index 0000000000..fa2759b7f0
--- /dev/null
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_geckoProfiler_control.js
@@ -0,0 +1,205 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+let getExtension = () => {
+ return ExtensionTestUtils.loadExtension({
+ background: async function () {
+ const runningListener = isRunning => {
+ if (isRunning) {
+ browser.test.sendMessage("started");
+ } else {
+ browser.test.sendMessage("stopped");
+ }
+ };
+
+ browser.test.onMessage.addListener(async (message, data) => {
+ let result;
+ switch (message) {
+ case "start":
+ result = await browser.geckoProfiler.start({
+ bufferSize: 10000,
+ windowLength: 20,
+ interval: 0.5,
+ features: ["js"],
+ threads: ["GeckoMain"],
+ });
+ browser.test.assertEq(undefined, result, "start returns nothing.");
+ break;
+ case "stop":
+ result = await browser.geckoProfiler.stop();
+ browser.test.assertEq(undefined, result, "stop returns nothing.");
+ break;
+ case "pause":
+ result = await browser.geckoProfiler.pause();
+ browser.test.assertEq(undefined, result, "pause returns nothing.");
+ browser.test.sendMessage("paused");
+ break;
+ case "resume":
+ result = await browser.geckoProfiler.resume();
+ browser.test.assertEq(undefined, result, "resume returns nothing.");
+ browser.test.sendMessage("resumed");
+ break;
+ case "test profile":
+ result = await browser.geckoProfiler.getProfile();
+ browser.test.assertTrue(
+ "libs" in result,
+ "The profile contains libs."
+ );
+ browser.test.assertTrue(
+ "meta" in result,
+ "The profile contains meta."
+ );
+ browser.test.assertTrue(
+ "threads" in result,
+ "The profile contains threads."
+ );
+ browser.test.assertTrue(
+ result.threads.some(t => t.name == "GeckoMain"),
+ "The profile contains a GeckoMain thread."
+ );
+ browser.test.sendMessage("tested profile");
+ break;
+ case "test dump to file":
+ try {
+ await browser.geckoProfiler.dumpProfileToFile(data.fileName);
+ browser.test.sendMessage("tested dump to file", {});
+ } catch (e) {
+ browser.test.sendMessage("tested dump to file", {
+ error: e.message,
+ });
+ }
+ break;
+ case "test profile as array buffer":
+ let arrayBuffer =
+ await browser.geckoProfiler.getProfileAsArrayBuffer();
+ browser.test.assertTrue(
+ arrayBuffer.byteLength >= 2,
+ "The profile array buffer contains data."
+ );
+ let textDecoder = new TextDecoder();
+ let profile = JSON.parse(textDecoder.decode(arrayBuffer));
+ browser.test.assertTrue(
+ "libs" in profile,
+ "The profile contains libs."
+ );
+ browser.test.assertTrue(
+ "meta" in profile,
+ "The profile contains meta."
+ );
+ browser.test.assertTrue(
+ "threads" in profile,
+ "The profile contains threads."
+ );
+ browser.test.assertTrue(
+ profile.threads.some(t => t.name == "GeckoMain"),
+ "The profile contains a GeckoMain thread."
+ );
+ browser.test.sendMessage("tested profile as array buffer");
+ break;
+ case "remove runningListener":
+ browser.geckoProfiler.onRunning.removeListener(runningListener);
+ browser.test.sendMessage("removed runningListener");
+ break;
+ }
+ });
+
+ browser.test.sendMessage("ready");
+
+ browser.geckoProfiler.onRunning.addListener(runningListener);
+ },
+
+ manifest: {
+ permissions: ["geckoProfiler"],
+ browser_specific_settings: {
+ gecko: {
+ id: "profilertest@mozilla.com",
+ },
+ },
+ },
+ });
+};
+
+let verifyProfileData = profile => {
+ ok("libs" in profile, "The profile contains libs.");
+ ok("meta" in profile, "The profile contains meta.");
+ ok("threads" in profile, "The profile contains threads.");
+ ok(
+ profile.threads.some(t => t.name == "GeckoMain"),
+ "The profile contains a GeckoMain thread."
+ );
+};
+
+add_task(async function testProfilerControl() {
+ const acceptedExtensionIdsPref =
+ "extensions.geckoProfiler.acceptedExtensionIds";
+ Services.prefs.setCharPref(
+ acceptedExtensionIdsPref,
+ "profilertest@mozilla.com"
+ );
+
+ let extension = getExtension();
+ await extension.startup();
+ await extension.awaitMessage("ready");
+ await extension.awaitMessage("stopped");
+
+ extension.sendMessage("start");
+ await extension.awaitMessage("started");
+
+ extension.sendMessage("test profile");
+ await extension.awaitMessage("tested profile");
+
+ const profilerPath = PathUtils.join(PathUtils.profileDir, "profiler");
+ let data, fileName, targetPath;
+
+ // test with file name only
+ fileName = "bar.profile";
+ targetPath = PathUtils.join(profilerPath, fileName);
+ extension.sendMessage("test dump to file", { fileName });
+ data = await extension.awaitMessage("tested dump to file");
+ equal(data.error, undefined, "No error thrown");
+ ok(await IOUtils.exists(targetPath), "Saved gecko profile exists.");
+ verifyProfileData(await IOUtils.readJSON(targetPath));
+
+ // test overwriting the formerly created file
+ extension.sendMessage("test dump to file", { fileName });
+ data = await extension.awaitMessage("tested dump to file");
+ equal(data.error, undefined, "No error thrown");
+ ok(await IOUtils.exists(targetPath), "Saved gecko profile exists.");
+ verifyProfileData(await IOUtils.readJSON(targetPath));
+
+ // test with a POSIX path, which is not allowed
+ fileName = "foo/bar.profile";
+ targetPath = PathUtils.join(profilerPath, ...fileName.split("/"));
+ extension.sendMessage("test dump to file", { fileName });
+ data = await extension.awaitMessage("tested dump to file");
+ equal(data.error, "Path cannot contain a subdirectory.");
+ ok(!(await IOUtils.exists(targetPath)), "Gecko profile hasn't been saved.");
+
+ // test with a non POSIX path which is not allowed
+ fileName = "foo\\bar.profile";
+ targetPath = PathUtils.join(profilerPath, ...fileName.split("\\"));
+ extension.sendMessage("test dump to file", { fileName });
+ data = await extension.awaitMessage("tested dump to file");
+ equal(data.error, "Path cannot contain a subdirectory.");
+ ok(!(await IOUtils.exists(targetPath)), "Gecko profile hasn't been saved.");
+
+ extension.sendMessage("test profile as array buffer");
+ await extension.awaitMessage("tested profile as array buffer");
+
+ extension.sendMessage("pause");
+ await extension.awaitMessage("paused");
+
+ extension.sendMessage("resume");
+ await extension.awaitMessage("resumed");
+
+ extension.sendMessage("stop");
+ await extension.awaitMessage("stopped");
+
+ extension.sendMessage("remove runningListener");
+ await extension.awaitMessage("removed runningListener");
+
+ await extension.unload();
+
+ Services.prefs.clearUserPref(acceptedExtensionIdsPref);
+});