Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/* Any copyright is dedicated to the Public Domain.
"use strict";
/* import-globals-from helper-backward-compat.js */
Services.scriptloader.loadSubScript(
CHROME_URL_ROOT + "helper-backward-compat.js",
this
);
Services.scriptloader.loadSubScript(
this
);
// The client waits for the xpcshell harness to start, and may wait for it to
// exit when something fails.
requestLongerTimeout(2);
const MULTIPROCESS_TOOLBOX_NAME = "Multiprocess Toolbox";
// See backward_compat_test_server/fixtures/xpcshell/test_debug_me.js.
const TEST_FILE = "test_debug_me.js";
// Check that an xpcshell test run with --jsdebugger can be debugged. This
// mirrors the "Check xpcshell debugging" step of the manual smoke test, see
// devtools/docs/contributor/release.md.
addCompatTask(async function (config) {
if (!config.xpcshell) {
ok(
true,
`xpcshell debugging is not tested with the ${config.server} server`
);
return;
}
const { host } = await runDevToolsServerCommand(config, "start-xpcshell");
await pushPref(
"devtools.aboutdebugging.network-locations",
JSON.stringify([host])
);
const { document, tab, window } = await openAboutDebugging();
const isConnected = await connectToXpcshell(host, document);
if (!isConnected) {
const { exitCode } = await runDevToolsServerCommand(
config,
"wait-xpcshell"
);
ok(false, `Failed to connect to ${host}, xpcshell exited with ${exitCode}`);
await removeTab(tab);
return;
}
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox(
document,
tab,
window,
MULTIPROCESS_TOOLBOX_NAME
);
const toolbox = getToolbox(devtoolsWindow);
info("Select the debugger");
await toolbox.selectTool("jsdebugger");
const dbg = createDebuggerContext(toolbox);
info("Wait for the test to pause on its first line");
await waitForPaused(dbg);
await waitForLoadedSource(dbg, TEST_FILE);
const source = findSource(dbg, TEST_FILE);
await assertPausedAtSourceAndLine(
dbg,
source.id,
getMarkedLine(dbg, `"use strict"`)
);
const breakpointLine = getMarkedLine(dbg, "// BREAKPOINT");
info(`Add a breakpoint on line ${breakpointLine} and resume`);
await addBreakpoint(dbg, TEST_FILE, breakpointLine);
await resume(dbg);
await waitForPaused(dbg);
await assertPausedAtSourceAndLine(dbg, source.id, breakpointLine);
info("Step over");
await stepOver(dbg);
await assertPausedAtSourceAndLine(
dbg,
source.id,
getMarkedLine(dbg, "// STEP")
);
info("Resume and wait for the xpcshell test to finish");
await resume(dbg);
const { exitCode } = await runDevToolsServerCommand(config, "wait-xpcshell");
is(exitCode, 0, "The xpcshell test passed");
await removeTab(devtoolsTab);
await removeTab(tab);
});
/**
* Retrieve the 1-based line number of the first line of the test file which
* contains the provided text.
*/
function getMarkedLine(dbg, text) {
const content = findSourceContent(dbg, TEST_FILE);
const index = content.value
.split("\n")
.findIndex(line => line.includes(text));
isnot(index, -1, `Found "${text}" in ${TEST_FILE}`);
return index + 1;
}
/**
* Same as connectToRuntime, but retries while the connection is refused.
* "start-xpcshell" returns as soon as the xpcshell harness starts, before it
* opens the DevTools server socket.
*
* @returns {boolean} Whether the connection succeeded.
*/
async function connectToXpcshell(host, document) {
// Connection can take some time to setup, use 40 attempts, 0.5s apart.
const MAX_ATTEMPTS = 40;
const ATTEMPT_INTERVAL_MS = 500;
const store = document.defaultView.AboutDebugging.store;
const sidebarItem = await waitFor(
() => findSidebarItemByText(host, document),
`Wait until the sidebar item for ${host} appears`,
// Use 100ms interval x 100 times for a total of 10 seconds
100,
100
);
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
info(`Connect to ${host}, attempt ${attempt}`);
const onConnected = waitForDispatch(store, "CONNECT_RUNTIME_SUCCESS");
const onFailed = waitForDispatch(store, "CONNECT_RUNTIME_FAILURE");
sidebarItem.querySelector(".qa-connect-button").click();
const { type } = await Promise.race([onConnected, onFailed]);
if (type == "CONNECT_RUNTIME_SUCCESS") {
await waitFor(
() => !sidebarItem.querySelector(".qa-connect-button"),
"Wait for the connect button to disappear"
);
return true;
}
await wait(ATTEMPT_INTERVAL_MS);
}
return false;
}