diff --git a/test/message/test-testpy-env-var-via-comment.js b/test/message/test-testpy-env-var-via-comment.js new file mode 100644 index 00000000000000..df56b08a93a77d --- /dev/null +++ b/test/message/test-testpy-env-var-via-comment.js @@ -0,0 +1,16 @@ +'use strict'; + +// Env: A_SET_ENV_VAR=A_SET_ENV_VAR_VALUE B_SET_ENV_VAR=B_SET_ENV_VAR_VALUE +// Flags: --test-isolation=none --expose-internals + +require('../common'); +const assert = require('node:assert'); + +// This test verifies that the Python test runner can set environment variables +// via comments in the test file, similar to how we set flags via comments. +// Ref: https://github.com/nodejs/node/issues/58179 +assert.strictEqual(process.env.A_SET_ENV_VAR, 'A_SET_ENV_VAR_VALUE'); +assert.strictEqual(process.env.B_SET_ENV_VAR, 'B_SET_ENV_VAR_VALUE'); +// Check interop with flags +const flag = require('internal/options').getOptionValue('--test-isolation'); +assert.strictEqual(flag, 'none'); diff --git a/test/message/test-testpy-env-var-via-comment.out b/test/message/test-testpy-env-var-via-comment.out new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/message/testcfg.py b/test/message/testcfg.py index 4be454b55c9053..5470fd2bd9a112 100644 --- a/test/message/testcfg.py +++ b/test/message/testcfg.py @@ -33,6 +33,7 @@ from functools import reduce FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") +ENV_PATTERN = re.compile(r"//\s+Env:(.*)") class MessageTestCase(test.TestCase): @@ -89,20 +90,33 @@ def IsFailureOutput(self, output): return True return False + def _parse_source_env(self, source): + env_match = ENV_PATTERN.search(source) + env = {} + if env_match: + for env_pair in env_match.group(1).strip().split(): + var, value = env_pair.split('=') + env[var] = value + return env + def GetLabel(self): return "%s %s" % (self.mode, self.GetName()) def GetName(self): return self.path[-1] - def GetCommand(self): + def GetRunConfiguration(self): result = [self.config.context.GetVm(self.arch, self.mode)] source = open(self.file).read() flags_match = FLAGS_PATTERN.search(source) + envs = self._parse_source_env(source) if flags_match: result += flags_match.group(1).strip().split() result.append(self.file) - return result + return { + 'command': result, + 'envs': envs + } def GetSource(self): return (open(self.file).read() diff --git a/test/parallel/test-testpy-env-var-via-comment.js b/test/parallel/test-testpy-env-var-via-comment.js new file mode 100644 index 00000000000000..fea2e788e174b8 --- /dev/null +++ b/test/parallel/test-testpy-env-var-via-comment.js @@ -0,0 +1,26 @@ +'use strict'; + +// Env: A_SET_ENV_VAR=A_SET_ENV_VAR_VALUE B_SET_ENV_VAR=B_SET_ENV_VAR_VALUE +// Flags: --test-isolation=none --expose-internals + +require('../common'); +const assert = require('node:assert'); +const { describe, it } = require('node:test'); + + +// This test verifies that the Python test runner can set environment variables +// via comments in the test file, similar to how we set flags via comments. +// Ref: https://github.com/nodejs/node/issues/58179 +describe('testpy env var via comment', () => { + it('should set env var A_SET_ENV_VAR', () => { + assert.strictEqual(process.env.A_SET_ENV_VAR, 'A_SET_ENV_VAR_VALUE'); + }); + it('should set env var B_SET_ENV_VAR', () => { + assert.strictEqual(process.env.B_SET_ENV_VAR, 'B_SET_ENV_VAR_VALUE'); + }); + + it('should interop with flags', () => { + const flag = require('internal/options').getOptionValue('--test-isolation'); + assert.strictEqual(flag, 'none'); + }); +}); diff --git a/test/pseudo-tty/test-testpy-env-var-via-comment.js b/test/pseudo-tty/test-testpy-env-var-via-comment.js new file mode 100644 index 00000000000000..df56b08a93a77d --- /dev/null +++ b/test/pseudo-tty/test-testpy-env-var-via-comment.js @@ -0,0 +1,16 @@ +'use strict'; + +// Env: A_SET_ENV_VAR=A_SET_ENV_VAR_VALUE B_SET_ENV_VAR=B_SET_ENV_VAR_VALUE +// Flags: --test-isolation=none --expose-internals + +require('../common'); +const assert = require('node:assert'); + +// This test verifies that the Python test runner can set environment variables +// via comments in the test file, similar to how we set flags via comments. +// Ref: https://github.com/nodejs/node/issues/58179 +assert.strictEqual(process.env.A_SET_ENV_VAR, 'A_SET_ENV_VAR_VALUE'); +assert.strictEqual(process.env.B_SET_ENV_VAR, 'B_SET_ENV_VAR_VALUE'); +// Check interop with flags +const flag = require('internal/options').getOptionValue('--test-isolation'); +assert.strictEqual(flag, 'none'); diff --git a/test/pseudo-tty/test-testpy-env-var-via-comment.out b/test/pseudo-tty/test-testpy-env-var-via-comment.out new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/pseudo-tty/testcfg.py b/test/pseudo-tty/testcfg.py index 4751188b44d30a..a955c4df2d7874 100644 --- a/test/pseudo-tty/testcfg.py +++ b/test/pseudo-tty/testcfg.py @@ -37,6 +37,7 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") PTY_HELPER = join(dirname(__file__), '../../tools/pseudo-tty.py') +ENV_PATTERN = re.compile(r"//\s+Env:(.*)") class TTYTestCase(test.TestCase): @@ -90,20 +91,33 @@ def IsFailureOutput(self, output): return True return False + def _parse_source_env(self, source): + env_match = ENV_PATTERN.search(source) + env = {} + if env_match: + for env_pair in env_match.group(1).strip().split(): + var, value = env_pair.split('=') + env[var] = value + return env + def GetLabel(self): return "%s %s" % (self.mode, self.GetName()) def GetName(self): return self.path[-1] - def GetCommand(self): + def GetRunConfiguration(self): result = [self.config.context.GetVm(self.arch, self.mode)] source = open(self.file).read() flags_match = FLAGS_PATTERN.search(source) + envs = self._parse_source_env(source) if flags_match: result += flags_match.group(1).strip().split() result.append(self.file) - return result + return { + 'command': result, + 'envs': envs + } def GetSource(self): return (open(self.file).read() diff --git a/test/testpy/__init__.py b/test/testpy/__init__.py index b5d9ea726ff76b..05d2460f924b2e 100644 --- a/test/testpy/__init__.py +++ b/test/testpy/__init__.py @@ -34,6 +34,7 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") LS_RE = re.compile(r'^test-.*\.m?js$') +ENV_PATTERN = re.compile(r"//\s+Env:(.*)") class SimpleTestCase(test.TestCase): @@ -48,6 +49,14 @@ def __init__(self, path, file, arch, mode, context, config, additional=None): else: self.additional_flags = [] + def _parse_source_env(self, source): + env_match = ENV_PATTERN.search(source) + env = {} + if env_match: + for env_pair in env_match.group(1).strip().split(): + var, value = env_pair.split('=') + env[var] = value + return env def GetLabel(self): return "%s %s" % (self.mode, self.GetName()) @@ -55,10 +64,11 @@ def GetLabel(self): def GetName(self): return self.path[-1] - def GetCommand(self): + def GetRunConfiguration(self): result = [self.config.context.GetVm(self.arch, self.mode)] source = open(self.file, encoding='utf8').read() flags_match = FLAGS_PATTERN.search(source) + envs = self._parse_source_env(source) if flags_match: flags = flags_match.group(1).strip().split() # The following block reads config.gypi to extract the v8_enable_inspector @@ -93,7 +103,10 @@ def GetCommand(self): result += [self.file] - return result + return { + 'command': result, + 'envs': envs + } def GetSource(self): return open(self.file).read() diff --git a/tools/test.py b/tools/test.py index ad3d0feb4edc17..08e10f18122c80 100755 --- a/tools/test.py +++ b/tools/test.py @@ -602,12 +602,21 @@ def RunCommand(self, command, env): def Run(self): try: - result = self.RunCommand(self.GetCommand(), { + run_configuration = self.GetRunConfiguration() + command = run_configuration['command'] + envs = {} + if 'envs' in run_configuration: + envs.update(run_configuration['envs']) + envs.update({ "TEST_SERIAL_ID": "%d" % self.serial_id, "TEST_THREAD_ID": "%d" % self.thread_id, "TEST_PARALLEL" : "%d" % self.parallel, "GITHUB_STEP_SUMMARY": "", }) + result = self.RunCommand( + command, + envs + ) finally: # Tests can leave the tty in non-blocking mode. If the test runner # tries to print to stdout/stderr after that and the tty buffer is