Repository navigation
Expand file tree
/
Copy pathnodeExecutable.test.ts
More file actions
82 lines (80 loc) · 5.5 KB
/
Copy pathnodeExecutable.test.ts
File metadata and controls
82 lines (80 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import * as assert from 'assert';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as sinon from 'sinon';
import { hostNodeRuntime, resolveNodeRuntime } from '../../interactive/nodeExecutable';
import { nodeEnvironment, prepareNodeRuntime } from '../../interactive/launcher';
suite('Interactive Node runtime', () => {
let root: string;
setup(() => { root = fs.mkdtempSync(path.join(os.tmpdir(), 'r-node-runtime-')); });
teardown(() => { fs.rmSync(root, { recursive: true, force: true }); });
test('uses the current extension host executable without a PATH lookup', () => {
const environment = sinon.stub(process.env, 'PATH').value(root);
const executable = sinon.stub(process, 'execPath').value(path.join(root, 'Code Helper (Plugin)'));
try {
assert.deepStrictEqual(hostNodeRuntime(), { executable: process.execPath, electron: !!process.versions.electron });
assert.deepStrictEqual(resolveNodeRuntime('', root), hostNodeRuntime());
assert.deepStrictEqual(resolveNodeRuntime(' ', root), hostNodeRuntime());
// A reload after an editor update must select the new host, not a cached path.
executable.value(path.join(root, 'updated-server', 'node'));
assert.strictEqual(hostNodeRuntime().executable, process.execPath);
} finally { executable.restore(); environment.restore(); }
});
test('resolves explicit names and quoted or relative paths without changing the automatic default', () => {
const directory = path.join(root, 'custom Node'); fs.mkdirSync(directory);
const name = process.platform === 'win32' ? 'node.exe' : 'node';
const executable = path.join(directory, name);
fs.writeFileSync(executable, '', { mode: 0o700 });
const environment = sinon.stub(process.env, 'PATH').value(directory);
try {
assert.deepStrictEqual(resolveNodeRuntime('', root), hostNodeRuntime());
const commands = [name, `"${executable}"`, path.join('.', 'custom Node', name)];
const homeRelative = path.relative(os.homedir(), executable);
// Windows can place the temp directory on a different drive from home.
if (!path.isAbsolute(homeRelative)) { commands.push(`~/${homeRelative}`); }
for (const command of commands) {
assert.deepStrictEqual(resolveNodeRuntime(command, root), { executable, electron: false });
}
for (const command of [path.join(root, 'missing-node'), directory]) {
assert.throws(() => resolveNodeRuntime(command, root), /r\.interactive\.nodePath.*remote server/);
}
} finally { environment.restore(); }
});
test('scopes Electron Node mode to its launch environment and removes debugger injection', () => {
const environment = { ELECTRON_RUN_AS_NODE: '1', VSCODE_INSPECTOR_OPTIONS: '{}', NODE_OPTIONS: '--require missing', PATH: root };
assert.deepStrictEqual(nodeEnvironment({ executable: 'Code', electron: true }, environment), { PATH: root, ELECTRON_RUN_AS_NODE: '1' });
assert.deepStrictEqual(nodeEnvironment({ executable: 'node', electron: false }, environment), { PATH: root });
assert.strictEqual(environment.NODE_OPTIONS, '--require missing');
});
test('reports a removed host runtime before creating session storage', async () => {
await assert.rejects(prepareNodeRuntime(root, { executable: path.join(root, 'removed-host'), electron: true }), /Reload VS Code.*VS Code Server/);
assert.deepStrictEqual(fs.readdirSync(root), []);
});
test('probes the Node version in Electron mode instead of its application version', async function () {
if (process.platform === 'win32') { this.skip(); }
const executable = path.join(root, 'Code Helper');
const runtime = { executable, electron: true };
const script = (version: string): string => `#!/bin/sh\n[ "$ELECTRON_RUN_AS_NODE" = 1 ] && [ "$1" = -p ] && [ "$2" = process.versions.node ] || exit 1\nprintf '${version}\\n'\n`;
fs.writeFileSync(executable, script('24.0.0'), { mode: 0o700 });
assert.deepStrictEqual(await prepareNodeRuntime(root, runtime), runtime);
for (const version of ['16.0.0', 'not node']) {
fs.writeFileSync(executable, script(version));
await assert.rejects(prepareNodeRuntime(root, runtime), /requires Node.js 18 or newer/);
}
});
test('validates explicit standalone Node without Electron mode and reports how to repair an override', async function () {
if (process.platform === 'win32') { this.skip(); }
const executable = path.join(root, 'standalone Node');
const script = (version: string): string => `#!/bin/sh\n[ -z "$ELECTRON_RUN_AS_NODE" ] && [ "$1" = -p ] && [ "$2" = process.versions.node ] || exit 1\nprintf '${version}\\n'\n`;
fs.writeFileSync(executable, script('24.0.0'), { mode: 0o700 });
const runtime = resolveNodeRuntime(executable, root);
assert.deepStrictEqual(await prepareNodeRuntime(root, runtime), { executable, electron: false });
for (const version of ['16.0.0', 'not node']) {
fs.writeFileSync(executable, script(version));
await assert.rejects(prepareNodeRuntime(root, runtime), /requires Node.js 18 or newer.*r\.interactive\.nodePath/);
}
fs.unlinkSync(executable);
await assert.rejects(prepareNodeRuntime(root, runtime), /Cannot run the Node.js runtime.*r\.interactive\.nodePath/);
});
});