Skip to content
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

test_runner: consolidate option parsing #53849

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 14 additions & 44 deletions lib/internal/main/test_runner.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
'use strict';

const {
NumberParseInt,
RegExpPrototypeExec,
StringPrototypeSplit,
} = primordials;

const {
prepareMainThreadExecution,
markBootstrapComplete,
} = require('internal/process/pre_execution');
const { getOptionValue } = require('internal/options');
const { isUsingInspector } = require('internal/util/inspector');
const { run } = require('internal/test_runner/runner');
const { setupTestReporters } = require('internal/test_runner/utils');
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
const {
codes: {
ERR_INVALID_ARG_VALUE,
},
} = require('internal/errors');

parseCommandLine,
setupTestReporters,
} = require('internal/test_runner/utils');
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => {
debug = fn;
});

prepareMainThreadExecution(false);
markBootstrapComplete();

let concurrency = getOptionValue('--test-concurrency') || true;
const {
perFileTimeout,
runnerConcurrency,
shard,
watchMode,
} = parseCommandLine();

let concurrency = runnerConcurrency;
let inspectPort;

if (isUsingInspector()) {
Expand All @@ -38,39 +35,12 @@ if (isUsingInspector()) {
inspectPort = process.debugPort;
}

let shard;
const shardOption = getOptionValue('--test-shard');
if (shardOption) {
if (!RegExpPrototypeExec(/^\d+\/\d+$/, shardOption)) {
process.exitCode = kGenericUserError;

throw new ERR_INVALID_ARG_VALUE(
'--test-shard',
shardOption,
'must be in the form of <index>/<total>',
);
}

const { 0: indexStr, 1: totalStr } = StringPrototypeSplit(shardOption, '/');

const index = NumberParseInt(indexStr, 10);
const total = NumberParseInt(totalStr, 10);

shard = {
__proto__: null,
index,
total,
};
}

const timeout = getOptionValue('--test-timeout') || Infinity;

const options = {
concurrency,
inspectPort,
watch: getOptionValue('--watch'),
watch: watchMode,
setup: setupTestReporters,
timeout,
timeout: perFileTimeout,
shard,
};
debug('test runner configuration:', options);
Expand Down
24 changes: 13 additions & 11 deletions lib/internal/test_runner/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ const {
readFileSync,
} = require('fs');
const { setupCoverageHooks } = require('internal/util');
const { getOptionValue } = require('internal/options');
const { tmpdir } = require('os');
const { join, resolve, relative, matchesGlob } = require('path');
const { fileURLToPath } = require('internal/url');
const { kMappings, SourceMap } = require('internal/source_map/source_map');
const { parseCommandLine } = require('internal/test_runner/utils');
const kCoverageFileRegex = /^coverage-(\d+)-(\d{13})-(\d+)\.json$/;
const kIgnoreRegex = /\/\* node:coverage ignore next (?<count>\d+ )?\*\//;
const kLineEndingRegex = /\r?\n$/u;
const kLineSplitRegex = /(?<=\r?\n)/u;
const kStatusRegex = /\/\* node:coverage (?<status>enable|disable) \*\//;
const excludeFileGlobs = getOptionValue('--test-coverage-exclude');
const includeFileGlobs = getOptionValue('--test-coverage-include');
const {
coverageExcludeGlobs,
coverageIncludeGlobs,
} = parseCommandLine();

class CoverageLine {
constructor(line, startOffset, src, length = src?.length) {
Expand Down Expand Up @@ -498,18 +500,18 @@ function shouldSkipFileCoverage(url, workingDirectory) {
const relativePath = relative(workingDirectory, absolutePath);

// This check filters out files that match the exclude globs.
if (excludeFileGlobs?.length > 0) {
for (let i = 0; i < excludeFileGlobs.length; ++i) {
if (matchesGlob(relativePath, excludeFileGlobs[i]) ||
matchesGlob(absolutePath, excludeFileGlobs[i])) return true;
if (coverageExcludeGlobs?.length > 0) {
for (let i = 0; i < coverageExcludeGlobs.length; ++i) {
if (matchesGlob(relativePath, coverageExcludeGlobs[i]) ||
matchesGlob(absolutePath, coverageExcludeGlobs[i])) return true;
}
}

// This check filters out files that do not match the include globs.
if (includeFileGlobs?.length > 0) {
for (let i = 0; i < includeFileGlobs.length; ++i) {
if (matchesGlob(relativePath, includeFileGlobs[i]) ||
matchesGlob(absolutePath, includeFileGlobs[i])) return false;
if (coverageIncludeGlobs?.length > 0) {
for (let i = 0; i < coverageIncludeGlobs.length; ++i) {
if (matchesGlob(relativePath, coverageIncludeGlobs[i]) ||
matchesGlob(absolutePath, coverageIncludeGlobs[i])) return false;
}
return true;
}
Expand Down
41 changes: 41 additions & 0 deletions lib/internal/test_runner/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
MathFloor,
MathMax,
MathMin,
NumberParseInt,
NumberPrototypeToFixed,
ObjectGetOwnPropertyDescriptor,
RegExp,
Expand All @@ -19,6 +20,7 @@ const {
StringPrototypePadStart,
StringPrototypeRepeat,
StringPrototypeSlice,
StringPrototypeSplit,
} = primordials;

const { AsyncResource } = require('async_hooks');
Expand Down Expand Up @@ -196,13 +198,19 @@ function parseCommandLine() {
const forceExit = getOptionValue('--test-force-exit');
const sourceMaps = getOptionValue('--enable-source-maps');
const updateSnapshots = getOptionValue('--test-update-snapshots');
const watchMode = getOptionValue('--watch');
const isChildProcess = process.env.NODE_TEST_CONTEXT === 'child';
const isChildProcessV8 = process.env.NODE_TEST_CONTEXT === 'child-v8';
let coverageExcludeGlobs;
let coverageIncludeGlobs;
let destinations;
let perFileTimeout;
let reporters;
let runnerConcurrency;
let testNamePatterns;
let testSkipPatterns;
let testOnlyFlag;
let shard;

if (isChildProcessV8) {
kBuiltinReporters.set('v8-serializer', 'internal/test_runner/reporter/v8-serializer');
Expand Down Expand Up @@ -232,9 +240,31 @@ function parseCommandLine() {
}

if (isTestRunner) {
perFileTimeout = getOptionValue('--test-timeout') || Infinity;
runnerConcurrency = getOptionValue('--test-concurrency') || true;
testOnlyFlag = false;
testNamePatterns = null;

const shardOption = getOptionValue('--test-shard');
if (shardOption) {
if (!RegExpPrototypeExec(/^\d+\/\d+$/, shardOption)) {
throw new ERR_INVALID_ARG_VALUE(
'--test-shard',
shardOption,
'must be in the form of <index>/<total>',
);
}

const indexAndTotal = StringPrototypeSplit(shardOption, '/');
shard = {
__proto__: null,
index: NumberParseInt(indexAndTotal[0], 10),
total: NumberParseInt(indexAndTotal[1], 10),
};
}
} else {
perFileTimeout = Infinity;
runnerConcurrency = 1;
const testNamePatternFlag = getOptionValue('--test-name-pattern');
testOnlyFlag = getOptionValue('--test-only');
testNamePatterns = testNamePatternFlag?.length > 0 ?
Expand All @@ -247,18 +277,29 @@ function parseCommandLine() {
ArrayPrototypeMap(testSkipPatternFlag, (re) => convertStringToRegExp(re, '--test-skip-pattern')) : null;
}

if (coverage) {
coverageExcludeGlobs = getOptionValue('--test-coverage-exclude');
coverageIncludeGlobs = getOptionValue('--test-coverage-include');
}

globalTestOptions = {
__proto__: null,
isTestRunner,
coverage,
coverageExcludeGlobs,
coverageIncludeGlobs,
forceExit,
perFileTimeout,
runnerConcurrency,
shard,
sourceMaps,
testOnlyFlag,
testNamePatterns,
testSkipPatterns,
updateSnapshots,
reporters,
destinations,
watchMode,
};

return globalTestOptions;
Expand Down
Loading