-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
test_runner: avoid reading process state directly in run() #62377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Refs: #53867 The run() function is exposed as a public API via node:test module. Previously, it accessed process.argv, process.execArgv, process.cwd(), and process.env directly, which meant programmatic API users could not fully control the test runner behavior. This change: - Captures process.argv, process.cwd(), process.env, and process.execArgv in the CLI entry point (main/test_runner.js) and passes them explicitly to run() as options - Adds a processExecArgv option for V8 flag propagation - Replaces process.env fallback in runTestFile() with opts.env - Replaces process.argv usage in getRunArgs() with globPatterns - Replaces process.env.NODE_TEST_CONTEXT check with env option - Maintains backwards compatibility: when options are not provided, run() falls back to process state as before
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,7 +30,11 @@ if (isUsingInspector() && options.isolation === 'process') { | |
| options.inspectPort = process.debugPort; | ||
| } | ||
|
|
||
| // Capture process state explicitly so run() does not need to access it. | ||
| options.globPatterns = ArrayPrototypeSlice(process.argv, 1); | ||
| options.cwd = process.cwd(); | ||
| options.env = process.env; | ||
| options.processExecArgv = process.execArgv; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How's this differ from execArgv?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah you're right, dropped it. The idea was to avoid the direct |
||
|
|
||
| debug('test runner configuration:', options); | ||
| run(options).on('test:summary', (data) => { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -167,6 +167,8 @@ function getRunArgs(path, { forceExit, | |
| only, | ||
| argv: suppliedArgs, | ||
| execArgv, | ||
| processExecArgv, | ||
| globPatterns, | ||
| rerunFailuresFilePath, | ||
|
||
| root: { timeout }, | ||
| cwd }) { | ||
|
|
@@ -183,7 +185,7 @@ function getRunArgs(path, { forceExit, | |
| */ | ||
| const nodeOptionsSet = new SafeSet(processNodeOptions); | ||
| const unknownProcessExecArgv = ArrayPrototypeFilter( | ||
| process.execArgv, | ||
| processExecArgv, | ||
| (arg) => !nodeOptionsSet.has(arg), | ||
| ); | ||
| ArrayPrototypePushApply(runArgs, unknownProcessExecArgv); | ||
|
|
@@ -214,7 +216,9 @@ function getRunArgs(path, { forceExit, | |
|
|
||
| if (path === kIsolatedProcessName) { | ||
| ArrayPrototypePush(runArgs, '--test'); | ||
| ArrayPrototypePushApply(runArgs, ArrayPrototypeSlice(process.argv, 1)); | ||
| if (globPatterns != null) { | ||
| ArrayPrototypePushApply(runArgs, globPatterns); | ||
| } | ||
| } else { | ||
| ArrayPrototypePush(runArgs, path); | ||
| } | ||
|
|
@@ -421,7 +425,7 @@ function runTestFile(path, filesWatcher, opts) { | |
| const subtest = opts.root.createSubtest(FileTest, testPath, testOpts, async (t) => { | ||
| const args = getRunArgs(path, opts); | ||
| const stdio = ['pipe', 'pipe', 'pipe']; | ||
| const env = { __proto__: null, NODE_TEST_CONTEXT: 'child-v8', ...(opts.env || process.env) }; | ||
| const env = { __proto__: null, NODE_TEST_CONTEXT: 'child-v8', ...opts.env }; | ||
|
|
||
| // Acquire a worker ID from the pool for process isolation mode | ||
| let workerId; | ||
|
|
@@ -648,11 +652,26 @@ function run(options = kEmptyObject) { | |
| functionCoverage = 0, | ||
| execArgv = [], | ||
| argv = [], | ||
| cwd = process.cwd(), | ||
| cwd, | ||
| processExecArgv, | ||
| rerunFailuresFilePath, | ||
|
Comment on lines
653
to
655
|
||
| env, | ||
| } = options; | ||
|
|
||
| // Default to process state when not explicitly provided, maintaining | ||
| // backwards compatibility for public API users while allowing the | ||
| // internal CLI entry point to pass these values explicitly. | ||
| const userProvidedEnv = env !== undefined; | ||
| if (cwd === undefined) { | ||
| cwd = process.cwd(); | ||
| } | ||
| if (env === undefined) { | ||
| env = process.env; | ||
| } | ||
| if (processExecArgv === undefined) { | ||
| processExecArgv = process.execArgv; | ||
| } | ||
|
|
||
| if (files != null) { | ||
| validateArray(files, 'options.files'); | ||
| } | ||
|
|
@@ -759,7 +778,7 @@ function run(options = kEmptyObject) { | |
| validatePath(globalSetupPath, 'options.globalSetupPath'); | ||
| } | ||
|
|
||
| if (env != null) { | ||
| if (userProvidedEnv) { | ||
| validateObject(env); | ||
|
|
||
| if (isolation === 'none') { | ||
|
|
@@ -830,13 +849,14 @@ function run(options = kEmptyObject) { | |
| isolation, | ||
| argv, | ||
| execArgv, | ||
| processExecArgv, | ||
| rerunFailuresFilePath, | ||
| env, | ||
| workerIdPool: isolation === 'process' ? workerIdPool : null, | ||
| }; | ||
|
|
||
| if (isolation === 'process') { | ||
| if (process.env.NODE_TEST_CONTEXT !== undefined) { | ||
| if (env.NODE_TEST_CONTEXT !== undefined) { | ||
| process.emitWarning('node:test run() is being called recursively within a test file. skipping running files.'); | ||
| root.postRun(); | ||
| return root.reporter; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
options.envis being set unconditionally, which makesrun()think the caller explicitly provided anenvoption. With--test-isolation=none,run()currently rejectsoptions.env, so this change will breaknode --test --test-isolation=none. Consider only setting/passingoptions.envin the CLI when isolation='process' (or updaterun()to treat this captured env as non-user-provided).