From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../tests/browser_target_command_watchTargets.js | 214 +++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 devtools/shared/commands/target/tests/browser_target_command_watchTargets.js (limited to 'devtools/shared/commands/target/tests/browser_target_command_watchTargets.js') diff --git a/devtools/shared/commands/target/tests/browser_target_command_watchTargets.js b/devtools/shared/commands/target/tests/browser_target_command_watchTargets.js new file mode 100644 index 0000000000..516780be01 --- /dev/null +++ b/devtools/shared/commands/target/tests/browser_target_command_watchTargets.js @@ -0,0 +1,214 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the TargetCommand's `watchTargets` function + +const TEST_URL = + "data:text/html;charset=utf-8," + encodeURIComponent(`
`); + +add_task(async function () { + // Enabled fission's pref as the TargetCommand is almost disabled without it + await pushPref("devtools.browsertoolbox.scope", "everything"); + // Disable the preloaded process as it gets created lazily and may interfere + // with process count assertions + await pushPref("dom.ipc.processPrelaunch.enabled", false); + // This preference helps destroying the content process when we close the tab + await pushPref("dom.ipc.keepProcessesAlive.web", 1); + + await testWatchTargets(); + await testThrowingInOnAvailable(); +}); + +async function testWatchTargets() { + info("Test TargetCommand watchTargets function"); + + const commands = await CommandsFactory.forMainProcess(); + const targetCommand = commands.targetCommand; + const { TYPES } = targetCommand; + + await targetCommand.startListening(); + + // Note that ppmm also includes the parent process, which is considered as a frame rather than a process + const originalProcessesCount = Services.ppmm.childCount - 1; + + info( + "Check that onAvailable is called for processes already created *before* the call to watchTargets" + ); + const targets = new Set(); + const topLevelTarget = targetCommand.targetFront; + const onAvailable = ({ targetFront }) => { + if (targets.has(targetFront)) { + ok(false, "The same target is notified multiple times via onAvailable"); + } + is( + targetFront.targetType, + TYPES.PROCESS, + "We are only notified about process targets" + ); + ok( + targetFront == topLevelTarget + ? targetFront.isTopLevel + : !targetFront.isTopLevel, + "isTopLevel property is correct" + ); + targets.add(targetFront); + }; + const onDestroyed = ({ targetFront }) => { + if (!targets.has(targetFront)) { + ok( + false, + "A target is declared destroyed via onDestroyed without being notified via onAvailable" + ); + } + is( + targetFront.targetType, + TYPES.PROCESS, + "We are only notified about process targets" + ); + ok( + !targetFront.isTopLevel, + "We are not notified about the top level target destruction" + ); + targets.delete(targetFront); + }; + await targetCommand.watchTargets({ + types: [TYPES.PROCESS], + onAvailable, + onDestroyed, + }); + is( + targets.size, + originalProcessesCount, + "retrieved the expected number of processes via watchTargets" + ); + // Start from 1 in order to ignore the parent process target, which is considered as a frame rather than a process + for (let i = 1; i < Services.ppmm.childCount; i++) { + const process = Services.ppmm.getChildAt(i); + const hasTargetWithSamePID = [...targets].find( + processTarget => processTarget.targetForm.processID == process.osPid + ); + ok( + hasTargetWithSamePID, + `Process with PID ${process.osPid} has been reported via onAvailable` + ); + } + + info( + "Check that onAvailable is called for processes created *after* the call to watchTargets" + ); + const previousTargets = new Set(targets); + const onProcessCreated = new Promise(resolve => { + const onAvailable2 = ({ targetFront }) => { + if (previousTargets.has(targetFront)) { + return; + } + targetCommand.unwatchTargets({ + types: [TYPES.PROCESS], + onAvailable: onAvailable2, + }); + resolve(targetFront); + }; + targetCommand.watchTargets({ + types: [TYPES.PROCESS], + onAvailable: onAvailable2, + }); + }); + const tab1 = await BrowserTestUtils.openNewForegroundTab({ + gBrowser, + url: TEST_URL, + forceNewProcess: true, + }); + const createdTarget = await onProcessCreated; + + // For some reason, creating a new tab purges processes created from previous tests + // so it is not reasonable to assert the side of `targets` as it may be lower than expected. + ok(targets.has(createdTarget), "The new tab process is in the list"); + + const processCountAfterTabOpen = targets.size; + + // Assert that onDestroyed is called for destroyed processes + const onProcessDestroyed = new Promise(resolve => { + const onAvailable3 = () => {}; + const onDestroyed3 = ({ targetFront }) => { + resolve(targetFront); + targetCommand.unwatchTargets({ + types: [TYPES.PROCESS], + onAvailable: onAvailable3, + onDestroyed: onDestroyed3, + }); + }; + targetCommand.watchTargets({ + types: [TYPES.PROCESS], + onAvailable: onAvailable3, + onDestroyed: onDestroyed3, + }); + }); + + BrowserTestUtils.removeTab(tab1); + + const destroyedTarget = await onProcessDestroyed; + is( + targets.size, + processCountAfterTabOpen - 1, + "The closed tab's process has been reported as destroyed" + ); + ok( + !targets.has(destroyedTarget), + "The destroyed target is no longer in the list" + ); + is( + destroyedTarget, + createdTarget, + "The destroyed target is the one that has been reported as created" + ); + + targetCommand.unwatchTargets({ + types: [TYPES.PROCESS], + onAvailable, + onDestroyed, + }); + + targetCommand.destroy(); + + await commands.destroy(); +} + +async function testThrowingInOnAvailable() { + info( + "Test TargetCommand watchTargets function when an exception is thrown in onAvailable callback" + ); + + const commands = await CommandsFactory.forMainProcess(); + const targetCommand = commands.targetCommand; + const { TYPES } = targetCommand; + + await targetCommand.startListening(); + + // Note that ppmm also includes the parent process, which is considered as a frame rather than a process + const originalProcessesCount = Services.ppmm.childCount - 1; + + info( + "Check that onAvailable is called for processes already created *before* the call to watchTargets" + ); + const targets = new Set(); + let thrown = false; + const onAvailable = ({ targetFront }) => { + if (!thrown) { + thrown = true; + throw new Error("Force an exception when processing the first target"); + } + targets.add(targetFront); + }; + await targetCommand.watchTargets({ types: [TYPES.PROCESS], onAvailable }); + is( + targets.size, + originalProcessesCount - 1, + "retrieved the expected number of processes via onAvailable. All but the first one where we have thrown." + ); + + targetCommand.destroy(); + + await commands.destroy(); +} -- cgit v1.2.3