Skip to content

Commit 1101967

Browse files
alan-agius4pull[bot]
authored andcommitted
1 parent cb16600 commit 1101967

File tree

1 file changed

+54
-15
lines changed

1 file changed

+54
-15
lines changed

tools/npm_integration_test/test_runner.js

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const VERBOSE_LOGS = !!process.env['VERBOSE_LOGS'];
1717
// Set to true if you want the /tmp folder created to persist after running `bazel test`
1818
const KEEP_TMP = false;
1919

20+
// bazelisk requires a $HOME environment variable for its cache
21+
process.env['HOME'] = tmp.dirSync({keep: KEEP_TMP, unsafeCleanup: !KEEP_TMP}).name;
22+
2023
function fail(...m) {
2124
console.error();
2225
console.error(`[${path.basename(__filename)}]`);
@@ -131,6 +134,22 @@ function copyToTmp(files) {
131134
tmp.dirSync({keep: KEEP_TMP, unsafeCleanup: !KEEP_TMP}).name);
132135
}
133136

137+
/**
138+
* Expands environment variables in a string of the form ${FOO_BAR}.
139+
*/
140+
function expandEnv(s) {
141+
if (!s) return s;
142+
const reg = /\$\{(\w+)\}/g;
143+
return s.replace(reg, (matched) => {
144+
const varName = matched.substring(2, matched.length - 1);
145+
if (process.env.hasOwnProperty(varName)) {
146+
return process.env[varName];
147+
} else {
148+
throw `Failed to expand unbound environment variable '${varName}' in '${s}'`;
149+
}
150+
});
151+
}
152+
134153
/**
135154
* TestRunner handles setting up the integration test and executing
136155
* the test commands based on the config.
@@ -153,31 +172,37 @@ class TestRunner {
153172
// and quoted arguments that contain spaces
154173
const split = command.split(' ');
155174
let binary = split[0];
156-
const args = split.slice(1);
175+
const args = split.slice(1).map(a => expandEnv(a));
157176
switch (binary) {
158177
case 'patch-package-json': {
159178
let packageJsonFile = 'package.json';
160179
if (args.length > 0) {
161180
packageJsonFile = args[0];
162181
}
163-
log(`running test command ${this.successful+1} of ${this.config.commands.length}: patching '${packageJsonFile}' in '${this.testRoot}'`);
182+
log(`running test command ${this.successful + 1} of ${
183+
this.config.commands.length}: patching '${packageJsonFile}' in '${this.testRoot}'`);
164184
this._patchPackageJson(packageJsonFile);
165185
} break;
166186

167187
default: {
168188
if (binary.startsWith('external/')) {
169189
binary = `../${binary.substring('external/'.length)}`;
170190
}
171-
const runfilesBinary = runfiles.resolveWorkspaceRelative(binary);
172-
binary = fs.existsSync(runfilesBinary) ? runfilesBinary : binary;
173-
log(`running test command ${this.successful+1} of ${this.config.commands.length}: '${binary} ${args.join(' ')}' in '${this.testRoot}'`);
191+
try {
192+
const runfilesBinary = runfiles.resolveWorkspaceRelative(binary);
193+
binary = (runfilesBinary && fs.existsSync(runfilesBinary)) ? runfilesBinary : binary;
194+
} catch (e) {
195+
}
196+
log(`running test command ${this.successful + 1} of ${this.config.commands.length}: '${
197+
binary} ${args.join(' ')}' in '${this.testRoot}'`);
174198
const spawnedProcess = spawnSync(binary, args, {cwd: this.testRoot, stdio: 'inherit'});
175199
if (spawnedProcess.error) {
176-
fail(
177-
`test command ${testRunner.successful+1} '${binary} ${args.join(' ')}' failed with ${spawnedProcess.error.code}`);
200+
fail(`test command ${testRunner.successful + 1} '${binary} ${
201+
args.join(' ')}' failed with ${spawnedProcess.error.code}`);
178202
}
179203
if (spawnedProcess.status) {
180-
log(`test command ${testRunner.successful+1} '${binary} ${args.join(' ')}' failed with status code ${spawnedProcess.status}`);
204+
log(`test command ${testRunner.successful + 1} '${binary} ${
205+
args.join(' ')}' failed with status code ${spawnedProcess.status}`);
181206
return spawnedProcess.status;
182207
}
183208
}
@@ -206,25 +231,29 @@ class TestRunner {
206231
if (contents.dependencies && contents.dependencies[key]) {
207232
replacements++;
208233
contents.dependencies[key] = replacement;
209-
log(`overriding dependencies['${key}'] npm package with 'file:${path}' in package.json file`);
234+
log(`overriding dependencies['${key}'] npm package with 'file:${
235+
path}' in package.json file`);
210236
}
211237
if (contents.devDependencies && contents.devDependencies[key]) {
212238
replacements++;
213239
contents.devDependencies[key] = replacement;
214-
log(`overriding devDependencies['${key}'] npm package with 'file:${path}' in package.json file`);
240+
log(`overriding devDependencies['${key}'] npm package with 'file:${
241+
path}' in package.json file`);
215242
}
216243
if (contents.resolutions && contents.resolutions[key]) {
217244
replacements++;
218245
contents.resolutions[key] = replacement;
219-
log(`overriding resolutions['${key}'] npm package with 'file:${path}' in package.json file`);
246+
log(`overriding resolutions['${key}'] npm package with 'file:${
247+
path}' in package.json file`);
220248
}
221249
// TODO: handle other formats for resolutions such as `some-package/${key}` or
222250
// `some-package/**/${key}`
223251
const altKey = `**/${key}`;
224252
if (contents.resolutions && contents.resolutions[altKey]) {
225253
replacements++;
226254
contents.resolutions[altKey] = replacement;
227-
log(`overriding resolutions['${altKey}'] npm package with 'file:${path}' in package.json file`);
255+
log(`overriding resolutions['${altKey}'] npm package with 'file:${
256+
path}' in package.json file`);
228257
}
229258
}
230259
// check packages that must be replaced
@@ -244,8 +273,8 @@ class TestRunner {
244273
const contentsEncoded = JSON.stringify(contents, null, 2);
245274
log(`package.json file:\n${contentsEncoded}`);
246275
if (failedPackages.length) {
247-
fail(
248-
`expected replacements of npm packages ${JSON.stringify(failedPackages)} not found; add these to the npm_packages attribute`);
276+
fail(`expected replacements of npm packages ${
277+
JSON.stringify(failedPackages)} not found; add these to the npm_packages attribute`);
249278
}
250279
if (replacements) {
251280
fs.writeFileSync(packageJson, contentsEncoded);
@@ -295,7 +324,8 @@ class TestRunner {
295324
log(`configuring test in-place under ${this.testRoot}`);
296325
} else {
297326
this.testRoot = copyToTmp(this.config.testFiles);
298-
log(`test files from '${rootDirectory(this.config.testFiles)}' copied to tmp folder ${this.testRoot}`);
327+
log(`test files from '${rootDirectory(this.config.testFiles)}' copied to tmp folder ${
328+
this.testRoot}`);
299329
}
300330
}
301331

@@ -334,6 +364,15 @@ log_verbose(`env: ${JSON.stringify(process.env, null, 2)}`);
334364
log_verbose(`config: ${JSON.stringify(config, null, 2)}`);
335365
log(`running in ${process.cwd()}`);
336366

367+
// remove --preserve-symlinks-main from node wrapper as it breaks node_modules/.bin files
368+
// run by yarn which must be resolved to their module location to work
369+
const isWindows = process.platform === 'win32';
370+
const nodePath = runfiles.resolve(
371+
`build_bazel_rules_nodejs/internal/node/_node_bin/${isWindows ? 'node.bat' : 'node'}`);
372+
const nodeContents =
373+
fs.readFileSync(nodePath, {encoding: 'utf-8'}).replace(' --preserve-symlinks-main ', ' ');
374+
fs.writeFileSync(nodePath, nodeContents, 'utf8');
375+
337376
const testRunner = new TestRunner(config);
338377
const result = testRunner.run();
339378
log(`${testRunner.successful} of ${config.commands.length} test commands successful`);

0 commit comments

Comments
 (0)