@itwin/certa
Version:
A mocha-based integration test runner
84 lines • 4.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.spawnChildProcess = spawnChildProcess;
exports.onExit = onExit;
exports.relaunchInElectron = relaunchInElectron;
exports.startDebugger = startDebugger;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
const child_process_1 = require("child_process");
const inspector = require("inspector");
/**
* Helper function for spawning a child process with the same cwd, env, stdout, and stderr as the current process.
* Processes spawned by this function will also have an IPC channel, so the may communicate with their parent via `process.send()`.
* @param command The command to run.
* @param args List of string arguments.
* @param env Environment vars to override in the child process.
* @param useIpc Whether to enable an IPC channel when spawning.
*/
function spawnChildProcess(command, args, env, useIpc = false) {
const childEnv = { ...process.env, ...(env || {}) };
// FIXME: We should be able to remove the useIpc param and just always enable it,
// but it's not safe to spawn electron with IPC enabled until https://github.com/electron/electron/issues/17044 is fixed.
const stdio = (useIpc) ? ["ipc", "pipe", "pipe"] : "pipe";
const childProcess = (0, child_process_1.spawn)(command, args, { stdio, cwd: process.cwd(), env: childEnv });
// For some reason, spawning using `stdio: "inherit"` results in some garbled output (for example, "✓" is printed as "ΓêÜ").
// Using `stdio: "pipe"` and manually redirecting the output here seems to work though.
childProcess.stdout?.on("data", (data) => process.stdout.write(data));
childProcess.stderr?.on("data", (data) => process.stderr.write(data));
return childProcess;
}
/** Returns a Promise that will be resolved with the given child process's exit code upon termination. */
async function onExit(child) {
return new Promise((resolve) => {
child.on("exit", (status) => resolve(status || 0));
});
}
/** Returns a Promise that will be resolved with the given child process's exit code upon termination. */
async function onExitElectronApp(child) {
let messageExitCode = 1; // Default to error
child.on("message", (message) => {
messageExitCode = message.exitCode;
});
return new Promise((resolve) => {
child.on("exit", (_exitCode) => {
// Note: Upgrading to electron 10 seems to cause the electron child process to always exit with 3221225477 = 0xC0000005(Access Violation).
// This causes the exitCode we pass to app.exit(_exitCode) to be lost. To work around this issue, we instead pass a message from the
// child process (see ElectronTestRunner), right before we call app.exit(). This message includes the exitCode based on the status of the
// test runs. See ElectronTestRunner.runTests, and the above listener to the "message" event.
resolve(messageExitCode);
});
});
}
/**
* Helper function for relaunching (as a child process) the current process in electron instead of node.
* Returns a promise that will be resolved with the exit code of the child process, once it terminates.
*/
async function relaunchInElectron() {
const args = process.argv.slice(1);
// '--debug' is not allowed in Electron and '--inspect' will automatically start a debugger,
// so we use custom parameter to indicate what we want to start debugger ourselves.
const debugIdx = args.indexOf("--debug");
if (debugIdx >= 0)
args[debugIdx] = "--debug-electron";
const child = spawnChildProcess(require("electron/index.js"), args, undefined, true);
return onExitElectronApp(child);
}
/**
* Activates the v8 inspector and starts listening on the given port, then breaks as soon as a debugger has connected.
* This is essentially what node does when run with `--inspect-brk={port}`, but doing this manually gives us more control
* over precisely _which_ child process connects to the debugger.
*
* For example, when using the chrome test runner, we want debug the original certa process ("node certa ...args") as the
* test "backend", but with the electron test runner, we want to debug a child process ("electron certa ...args").
* @param port Port to listen on for inspector connections.
*/
function startDebugger(port) {
// Don't try to activate if there's already an active inspector.
if (inspector.url())
return;
inspector.open(port, undefined, true);
}
//# sourceMappingURL=SpawnUtils.js.map