summaryrefslogtreecommitdiffstats
path: root/tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js')
-rw-r--r--tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js b/tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js
new file mode 100644
index 0000000000..14d76dbcaf
--- /dev/null
+++ b/tools/profiler/tests/browser/browser_test_profile_capture_by_pid.js
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function ProcessHasSamplerThread(process) {
+ return process.threads.some(t => t.name == "SamplerThread");
+}
+
+async function GetPidsWithSamplerThread() {
+ let parentProc = await ChromeUtils.requestProcInfo();
+
+ let pids = parentProc.children
+ .filter(ProcessHasSamplerThread)
+ .map(proc => proc.pid);
+ if (ProcessHasSamplerThread(parentProc)) {
+ pids.unshift(parentProc.pid);
+ }
+ return pids;
+}
+
+// fnFilterWithContentId: Called with content child pid, returns filters to use.
+// E.g.: 123 => ["GeckoMain", "pid:123"], or 123 => ["pid:456"].
+async function test_with_filter(fnFilterWithContentId) {
+ Assert.ok(!Services.profiler.IsActive());
+ info("Clear the previous pages just in case we still some open tabs.");
+ await Services.profiler.ClearAllPages();
+
+ info("Open a tab with single_frame.html in it.");
+ const url = BASE_URL + "single_frame.html";
+ return BrowserTestUtils.withNewTab(url, async function (contentBrowser) {
+ const contentPid = await SpecialPowers.spawn(contentBrowser, [], () => {
+ return Services.appinfo.processID;
+ });
+
+ Assert.deepEqual(
+ await GetPidsWithSamplerThread(),
+ [],
+ "There should be no SamplerThreads before starting the profiler"
+ );
+
+ info("Start the profiler to test filters including 'pid:<content>'.");
+ await startProfiler({ threads: fnFilterWithContentId(contentPid) });
+
+ let pidsWithSamplerThread = null;
+ await TestUtils.waitForCondition(
+ async function () {
+ let pidsStringBefore = JSON.stringify(pidsWithSamplerThread);
+ pidsWithSamplerThread = await GetPidsWithSamplerThread();
+ return JSON.stringify(pidsWithSamplerThread) == pidsStringBefore;
+ },
+ "Wait for sampler threads to stabilize after profiler start",
+ /* interval (ms) */ 250,
+ /* maxTries */ 10
+ );
+
+ info("Capture the profile data.");
+ const profile = await waitSamplingAndStopAndGetProfile();
+
+ await TestUtils.waitForCondition(async function () {
+ return !(await GetPidsWithSamplerThread()).length;
+ }, "Wait for all sampler threads to stop after profiler stop");
+
+ return { contentPid, pidsWithSamplerThread, profile };
+ });
+}
+
+add_task(async function browser_test_profile_capture_along_with_content_pid() {
+ const { contentPid, pidsWithSamplerThread, profile } = await test_with_filter(
+ contentPid => ["GeckoMain", "pid:" + contentPid]
+ );
+
+ Assert.greater(
+ pidsWithSamplerThread.length,
+ 2,
+ "There should be lots of SamplerThreads after starting the profiler"
+ );
+
+ let contentProcessIndex = profile.processes.findIndex(
+ p => p.threads[0].pid == contentPid
+ );
+ Assert.notEqual(
+ contentProcessIndex,
+ -1,
+ "The content process should be present"
+ );
+
+ // Note: Some threads may not be registered, so we can't expect that many. But
+ // 10 is much more than the default 4.
+ Assert.greater(
+ profile.processes[contentProcessIndex].threads.length,
+ 10,
+ "The content process should have many threads"
+ );
+
+ Assert.equal(
+ profile.threads.length,
+ 1,
+ "The parent process should have only one thread"
+ );
+ Assert.equal(
+ profile.threads[0].name,
+ "GeckoMain",
+ "The parent process should have the main thread"
+ );
+});
+
+add_task(async function browser_test_profile_capture_along_with_other_pid() {
+ const parentPid = Services.appinfo.processID;
+ const { contentPid, pidsWithSamplerThread, profile } = await test_with_filter(
+ contentPid => ["GeckoMain", "pid:" + parentPid]
+ );
+
+ Assert.greater(
+ pidsWithSamplerThread.length,
+ 2,
+ "There should be lots of SamplerThreads after starting the profiler"
+ );
+
+ let contentProcessIndex = profile.processes.findIndex(
+ p => p.threads[0].pid == contentPid
+ );
+ Assert.notEqual(
+ contentProcessIndex,
+ -1,
+ "The content process should be present"
+ );
+
+ Assert.equal(
+ profile.processes[contentProcessIndex].threads.length,
+ 1,
+ "The content process should have only one thread"
+ );
+
+ // Note: Some threads may not be registered, so we can't expect that many. But
+ // 10 is much more than the default 4.
+ Assert.greater(
+ profile.threads.length,
+ 10,
+ "The parent process should have many threads"
+ );
+});
+
+add_task(async function browser_test_profile_capture_by_only_content_pid() {
+ const parentPid = Services.appinfo.processID;
+ const { contentPid, pidsWithSamplerThread, profile } = await test_with_filter(
+ contentPid => ["pid:" + contentPid]
+ );
+
+ // The sampler thread always runs in the parent process, see bug 1754100.
+ Assert.deepEqual(
+ pidsWithSamplerThread,
+ [parentPid, contentPid],
+ "There should only be SamplerThreads in the parent and the target child"
+ );
+
+ Assert.equal(
+ profile.processes.length,
+ 1,
+ "There should only be one child process"
+ );
+ // Note: Some threads may not be registered, so we can't expect that many. But
+ // 10 is much more than the default 4.
+ Assert.greater(
+ profile.processes[0].threads.length,
+ 10,
+ "The child process should have many threads"
+ );
+ Assert.equal(
+ profile.processes[0].threads[0].pid,
+ contentPid,
+ "The only child process should be our content"
+ );
+});
+
+add_task(async function browser_test_profile_capture_by_only_parent_pid() {
+ const parentPid = Services.appinfo.processID;
+ const { pidsWithSamplerThread, profile } = await test_with_filter(
+ contentPid => ["pid:" + parentPid]
+ );
+
+ Assert.deepEqual(
+ pidsWithSamplerThread,
+ [parentPid],
+ "There should only be a SamplerThread in the parent"
+ );
+
+ // Note: Some threads may not be registered, so we can't expect that many. But
+ // 10 is much more than the default 4.
+ Assert.greater(
+ profile.threads.length,
+ 10,
+ "The parent process should have many threads"
+ );
+ Assert.equal(
+ profile.processes.length,
+ 0,
+ "There should be no child processes"
+ );
+});