blob: 61eae73dc38b0aaf7943403bf4942e1f9ddf1ace [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {type ChildProcess, spawn} from 'node:child_process';
import * as path from 'node:path';
const HOSTED_MODE_SERVER_PATH = path.join(__dirname, '..', '..', 'scripts', 'hosted_mode', 'server.js');
const cwd = path.join(__dirname, '..', '..');
let runningServer: ChildProcess|undefined;
/**
* Starts a hosted mode server on any available port and returns the port number
* once the server is ready to receive requests.
**/
export function startServer(server: 'hosted-mode', commandLineArgs: string[]): Promise<number> {
if (runningServer) {
throw new Error('Server was already started.');
}
function handleServerError(error: Error) {
console.error(`Server error: ${error}`);
}
const serverExecutable = {
'hosted-mode': HOSTED_MODE_SERVER_PATH,
}[server];
// Copy the current env and append the port.
const env = Object.create(process.env);
env.PORT = 0; // 0 means request a free port from the OS.
return new Promise((resolve, reject) => {
// We open the server with an IPC channel so that it can report the port it
// used back to us. For parallel test mode, we need to avoid specifying a
// port directly and instead request any free port, which is what port 0
// signifies to the OS.
const processArguments = [serverExecutable, ...commandLineArgs];
runningServer = spawn(process.execPath, processArguments, {cwd, env, stdio: ['pipe', 'pipe', 'pipe', 'ipc']});
runningServer.on('message', message => {
if (message === 'ERROR') {
reject('Could not start server');
} else {
resolve(Number(message));
}
});
runningServer.on('error', handleServerError);
if (runningServer.stderr) {
runningServer.stderr.on('data', handleServerError);
}
});
}
process.on('exit', stopServer);
export function stopServer() {
runningServer?.kill();
}