test: add parseTestMetadata support · nodejs/node@e517792

@@ -58,8 +58,16 @@ const hasSQLite = Boolean(process.versions.sqlite);

58585959

const hasQuic = hasCrypto && !!process.config.variables.node_quic;

606061-

function parseTestFlags(filename = process.argv[1]) {

62-

// The copyright notice is relatively big and the flags could come afterwards.

61+

/**

62+

* Parse test metadata from the specified file.

63+

* @param {string} filename - The name of the file to parse.

64+

* @returns {{

65+

* flags: string[],

66+

* envs: Record<string, string>

67+

* }} An object containing the parsed flags and environment variables.

68+

*/

69+

function parseTestMetadata(filename = process.argv[1]) {

70+

// The copyright notice is relatively big and the metadata could come afterwards.

6371

const bytesToRead = 1500;

6472

const buffer = Buffer.allocUnsafe(bytesToRead);

6573

const fd = fs.openSync(filename, 'r');

@@ -68,19 +76,33 @@ function parseTestFlags(filename = process.argv[1]) {

6876

const source = buffer.toString('utf8', 0, bytesRead);

69777078

const flagStart = source.search(/\/\/ Flags:\s+--/) + 10;

71-72-

if (flagStart === 9) {

73-

return [];

79+

let flags = [];

80+

if (flagStart !== 9) {

81+

let flagEnd = source.indexOf('\n', flagStart);

82+

if (source[flagEnd - 1] === '\r') {

83+

flagEnd--;

84+

}

85+

flags = source

86+

.substring(flagStart, flagEnd)

87+

.split(/\s+/)

88+

.filter(Boolean);

7489

}

75-

let flagEnd = source.indexOf('\n', flagStart);

76-

// Normalize different EOL.

77-

if (source[flagEnd - 1] === '\r') {

78-

flagEnd--;

90+91+

const envStart = source.search(/\/\/ Env:\s+/) + 8;

92+

let envs = {};

93+

if (envStart !== 7) {

94+

let envEnd = source.indexOf('\n', envStart);

95+

if (source[envEnd - 1] === '\r') {

96+

envEnd--;

97+

}

98+

const envArray = source

99+

.substring(envStart, envEnd)

100+

.split(/\s+/)

101+

.filter(Boolean);

102+

envs = Object.fromEntries(envArray.map((env) => env.split('=')));

79103

}

80-

return source

81-

.substring(flagStart, flagEnd)

82-

.split(/\s+/)

83-

.filter(Boolean);

104+105+

return { flags, envs };

84106

}

8510786108

// Check for flags. Skip this for workers (both, the `cluster` module and

@@ -93,7 +115,7 @@ if (process.argv.length === 2 &&

93115

hasCrypto &&

94116

require('cluster').isPrimary &&

95117

fs.existsSync(process.argv[1])) {

96-

const flags = parseTestFlags();

118+

const { flags, envs } = parseTestMetadata();

97119

for (const flag of flags) {

98120

if (!process.execArgv.includes(flag) &&

99121

// If the binary is build without `intl` the inspect option is

@@ -102,11 +124,20 @@ if (process.argv.length === 2 &&

102124

console.log(

103125

'NOTE: The test started as a child_process using these flags:',

104126

inspect(flags),

127+

'And these environment variables:',

128+

inspect(envs),

105129

'Use NODE_SKIP_FLAG_CHECK to run the test with the original flags.',

106130

);

107131

const { spawnSync } = require('child_process');

108132

const args = [...flags, ...process.execArgv, ...process.argv.slice(1)];

109-

const options = { encoding: 'utf8', stdio: 'inherit' };

133+

const options = {

134+

encoding: 'utf8',

135+

stdio: 'inherit',

136+

env: {

137+

...process.env,

138+

...envs,

139+

},

140+

};

110141

const result = spawnSync(process.execPath, args, options);

111142

if (result.signal) {

112143

process.kill(0, result.signal);

@@ -912,7 +943,7 @@ const common = {

912943

mustSucceed,

913944

nodeProcessAborted,

914945

PIPE,

915-

parseTestFlags,

946+

parseTestMetadata,

916947

platformTimeout,

917948

printSkipMessage,

918949

pwdCommand,