blob: 0335ff307733272b9213227c233dbba429bec551 [file]
import * as assert from 'assert';
import * as cp from 'child_process';
import * as os from 'os';
import * as path from 'path';
import * as rimraf from 'rimraf';
const requireScript = path.resolve(path.join(__dirname, '..', '..', 'register.js'));
const nodeDir = path.join(os.tmpdir(), 'node-patches-test-tmp', '_node_bin');
// tslint:disable-next-line:no-any
function assertPatched(prefix: string, arr: any) {
const [execPath, execArgv, argv, pathEnv] = arr;
assert.deepStrictEqual(
path.join(nodeDir, 'node'), execPath,
prefix + ' exec path has been rewritten to subprocess proxy');
assert.deepStrictEqual(
path.join(nodeDir, 'node'), argv[0],
prefix + ' argv[0] has been rewritten to subprocess proxy');
let found = false;
(execArgv as string[]).forEach((v) => {
if (!found) found = v.indexOf('node-patches/register.js') > -1
})
assert.ok(
found,
prefix +
' the require script must be in process.execArgv in order for node to use it in worker threads.');
// this has a downside in that a user can delete it from execArgv and workerThreads will not use
// the loader. in the future we may remove this loophole by making process.execArgv a getter or
// something.
assert.deepStrictEqual(
nodeDir, pathEnv.split(path.delimiter)[0],
prefix + ' the highest priority directory in the PATH must be the node shim dir.');
}
describe('spawning child processes', () => {
it('get patched if run as shell script.', () => {
const res = cp.execSync(`NP_SUBPROCESS_NODE_DIR=${nodeDir} node -r ${
requireScript} -e 'console.log(JSON.stringify([process.execPath,process.execArgv,process.argv,process.env.PATH]))'`);
assertPatched('', JSON.parse(res + ''));
});
it('overwrites spawn related variables correctly.', () => {
const res = cp.execSync(`NP_SUBPROCESS_NODE_DIR=${nodeDir} node -r ${requireScript} ${
path.join(__dirname, 'worker-threads-script.js')}`);
const {mainThread, worker} = JSON.parse(res + '');
assertPatched('main:', mainThread);
assertPatched('worker:', worker);
});
it('can spawn node from the shell', () => {
const res = cp.execSync(`NP_SUBPROCESS_NODE_DIR=${nodeDir} node -r ${requireScript} ${
path.join(__dirname, 'shell-script.js')}`);
// TODO: this is broken if no environment is passed and a new bash is executed
// reading only the rc files to build the environment.
// assert.fail('this doesn't work')
const {result} = JSON.parse(res + '');
assertPatched('shell spawn:', result);
});
it('can spawn node from spawn', () => {
const res = cp.execSync(
`NP_SUBPROCESS_NODE_DIR=${nodeDir} node -r ${requireScript} ${
path.join(__dirname, 'spawn-script.js')}`,
{env: process.env});
const {result} = JSON.parse(res + '');
assertPatched('spawn spawn:', result);
});
after(() => {
rimraf.sync(nodeDir);
});
});