From 11bd5fe0f50821eccaa8beef08a2999bce68f2d0 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 31 Aug 2022 21:33:39 -0400 Subject: [PATCH] test_runner: add --test-name-pattern CLI flag This commit adds support for running tests that match a regular expression. Fixes: https://github.com/nodejs/node/issues/42984 TODO: Still needs tests and docs. --- lib/internal/test_runner/test.js | 21 +++++++++++++++++++-- src/node_options.cc | 3 +++ src/node_options.h | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 006cd0fd5f77d5..898d605cd7216b 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -1,9 +1,11 @@ 'use strict'; const { + ArrayPrototypeMap, ArrayPrototypePush, ArrayPrototypeReduce, ArrayPrototypeShift, ArrayPrototypeSlice, + ArrayPrototypeSome, ArrayPrototypeUnshift, FunctionPrototype, MathMax, @@ -12,6 +14,7 @@ const { PromisePrototypeThen, PromiseResolve, ReflectApply, + RegExpPrototypeExec, SafeMap, SafePromiseAll, SafePromiseRace, @@ -57,6 +60,10 @@ const kDefaultTimeout = null; const noop = FunctionPrototype; const isTestRunner = getOptionValue('--test'); const testOnlyFlag = !isTestRunner && getOptionValue('--test-only'); +const testNamePatternFlag = isTestRunner ? null : + getOptionValue('--test-name-pattern'); +const testNamePatterns = testNamePatternFlag?.length > 0 ? + ArrayPrototypeMap(testNamePatternFlag, (re) => new RegExp(re)) : null; // TODO(cjihrig): Use uv_available_parallelism() once it lands. const rootConcurrency = isTestRunner ? MathMax(cpus().length - 1, 1) : 1; const kShouldAbort = Symbol('kShouldAbort'); @@ -192,6 +199,17 @@ class Test extends AsyncResource { this.timeout = timeout; } + if (testNamePatterns !== null) { + const match = this instanceof TestHook || ArrayPrototypeSome( + testNamePatterns, + (re) => RegExpPrototypeExec(re, name) !== null + ); + + if (!match) { + skip = 'test name does not match pattern'; + } + } + if (testOnlyFlag && !this.only) { skip = '\'only\' option not set'; } @@ -207,7 +225,6 @@ class Test extends AsyncResource { validateAbortSignal(signal, 'options.signal'); this.#outerSignal?.addEventListener('abort', this.#abortHandler); - this.fn = fn; this.name = name; this.parent = parent; @@ -666,6 +683,7 @@ class ItTest extends Test { return { ctx: { signal: this.signal, name: this.name }, args: [] }; } } + class Suite extends Test { constructor(options) { super(options); @@ -701,7 +719,6 @@ class Suite extends Test { return; } - const hookArgs = this.getRunArgs(); await this[kRunHook]('before', hookArgs); const stopPromise = stopTest(this.timeout, this.signal); diff --git a/src/node_options.cc b/src/node_options.cc index b9ffafb7cacd6c..67c3acc34d760e 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -529,6 +529,9 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--test", "launch test runner on startup", &EnvironmentOptions::test_runner); + AddOption("--test-name-pattern", + "run tests whose name matches this regular expression", + &EnvironmentOptions::test_name_pattern); AddOption("--test-only", "run tests with 'only' option set", &EnvironmentOptions::test_only, diff --git a/src/node_options.h b/src/node_options.h index ca43192d85a4b4..cc2217daa6d41c 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -152,6 +152,7 @@ class EnvironmentOptions : public Options { std::string redirect_warnings; std::string diagnostic_dir; bool test_runner = false; + std::vector test_name_pattern; bool test_only = false; bool test_udp_no_try_send = false; bool throw_deprecation = false;