Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
18ae2c3
tools: lint osx shell scripts
LiviaMedeiros Apr 14, 2022
ef5ab81
doc: fix `added:` info for `outgoingMessage.{,un}cork()`
lpinca Apr 14, 2022
2a07a9f
doc: document the 'close' and 'finish' events
lpinca Apr 14, 2022
be44b1f
test: improve test coverage of internal/blob
kuriyosh Apr 14, 2022
deb3cf4
test: remove the legacy url parser function
cola119 Apr 14, 2022
78a860a
test_runner: add initial CLI runner
cjihrig Apr 15, 2022
2f38b48
meta: move mmarchini to emeritus
mmarchini Apr 16, 2022
6b7c35e
doc: delete mdb_v8 from diagnostic tooling support tiers
tony-go Apr 16, 2022
1a7af63
src: large page attributing an id on Linux
devnexen Apr 17, 2022
294664e
deps: upgrade npm to 8.7.0
Apr 14, 2022
c50309c
doc: fix `added:` info for `outgoingMessage.writable*`
lpinca Apr 17, 2022
14893c5
meta: update AUTHORS
nodejs-github-bot Apr 17, 2022
47c0481
tools: update lint-md-dependencies
nodejs-github-bot Apr 17, 2022
93fd77a
tools: update doc to highlight.js@11.5.1
nodejs-github-bot Apr 17, 2022
4694f5b
async_hooks: avoid decrementing iterator after erase
dygabo Apr 17, 2022
459546b
benchmark: fix misc/startup failure
aduh95 Apr 17, 2022
d77c59d
doc: improve fragment (`:target`) anchors behavior on HTML version
aduh95 Apr 17, 2022
4c30936
doc: copyedit http.OutgoingMessage documentation
lpinca Apr 17, 2022
222b3e6
doc: close tag in n-api.md
LiviaMedeiros Apr 18, 2022
962d80b
doc: add documentation for inherited methods
lpinca Apr 18, 2022
29c8411
bootstrap: move embedded snapshot to SnapshotBuilder
joyeecheung Apr 11, 2022
6bd2420
bootstrap: use the isolate snapshot in workers
joyeecheung Apr 11, 2022
d311916
test: fix calculations in test-worker-resource-limits
joyeecheung Apr 11, 2022
025b3e7
doc: consolidate use of multiple-byte units
aduh95 Apr 19, 2022
7c97347
build: improve the format-cpp error message
RaisinTen Apr 19, 2022
c3922af
worker: add hasRef() to the handle object
RaisinTen Apr 19, 2022
46c880b
doc: clarify core modules that can be loaded without a prefix
aduh95 Apr 19, 2022
3d65a3b
doc: add `node:` prefix for all core modules
aduh95 Apr 20, 2022
b7e9dd0
src: use `node:` prefix in example
aduh95 Apr 20, 2022
5d15eb1
build: fix format-cpp
RaisinTen Apr 20, 2022
1976284
src: define fs.constants.S_IWUSR & S_IRUSR for Win
ilg-ul Apr 21, 2022
33ac027
meta: move one or more collaborators to emeritus
nodejs-github-bot Apr 18, 2022
6225370
doc: fix version history for Loaders API
aduh95 Apr 21, 2022
c32f76d
doc: fix example in assert.md
LiviaMedeiros Apr 21, 2022
8476ffb
test: use `assert.match()` instead of `assert(regex.test())`
aduh95 Apr 21, 2022
6fa080c
doc: delete heapdump from diagnostic tooling support tiers
tony-go Apr 21, 2022
d9f3f05
doc: fix outdated documentation for `family` property
aduh95 Apr 21, 2022
59da133
doc: add maintaining-webassembly.md
mhdawson Apr 8, 2022
c46e7bb
doc: add @kuriyosh to collaborators
kuriyosh Apr 22, 2022
c6c1dc5
doc: order `vm.Module` linker arguments correctly
SimenB Apr 22, 2022
b0f7c4c
lib,src: implement WebAssembly Web API
tniessen Apr 23, 2022
a19fb60
v8: export more fields in getHeapStatistics
theanarkh Apr 23, 2022
7681e60
crypto: validate `this` in all webcrypto methods and getters
panva Apr 23, 2022
f9994e2
build: improve reliability of find_python.cmd script
lpinca Apr 23, 2022
d33cbab
lib: remove experimental warning from FormData
meixg Apr 24, 2022
4050b0d
build: enable V8's shared read-only heap
targos Apr 24, 2022
494650c
src,crypto: remove uses of AllocatedBuffer from crypto_ec.cc
RaisinTen Apr 24, 2022
0e16120
errors,vm: update error and use cause
devsnek Apr 22, 2022
37364ab
test: fix flaky HTTP server tests
tniessen Apr 24, 2022
fdc6503
meta: update AUTHORS
nodejs-github-bot Apr 24, 2022
97fc00a
tools: update eslint to 8.14.0
nodejs-github-bot Apr 24, 2022
1b5856a
wasi: remove unecessary null check
mhdawson Apr 24, 2022
9b61ac2
doc: update WebAssembly strategy with Wasm Web API
tniessen Apr 25, 2022
c3c5fe7
tools: bump jsdoccomment from 0.22.1 to 0.29.0
Trott Apr 25, 2022
7b70144
test: skip test that cannot pass under --node-builtin-modules-path
GeoffreyBooth Apr 25, 2022
ad82694
lib,src: use Response URL as WebAssembly location
tniessen Apr 25, 2022
2d76f72
doc: elevate node-clinic diagnostic tier
RafaelGSS Apr 20, 2022
cd2f5a4
doc: add primordials guidelines
aduh95 May 11, 2021
48bbb73
fs: fix mkdirSync so ENOSPC is correctly reported
santigimeno Apr 26, 2022
0725064
test: fix port in net-perf_hooks
LiviaMedeiros Apr 26, 2022
2f849a4
doc: fix markdown formatting in primordials.md
tniessen Apr 27, 2022
59c07a9
test: check ecdsa psychic signature
panva Apr 27, 2022
b85a11c
test: improve lib/internal/test_runner/test.js coverage
fossamagna Apr 27, 2022
fe65996
doc: clarify guide on testing internal errors
LiviaMedeiros Apr 27, 2022
a6e1e7a
doc,test: add tests and docs for duplex.fromWeb and duplex.toWeb
ErickWendel Apr 28, 2022
336242a
errors,console: refactor to use ES2021 syntax
xtx1130 Apr 28, 2022
7fae2c9
deps: add template for generated headers
danbev Apr 5, 2022
e8734a4
deps: add note about removing asm archs
danbev Apr 14, 2022
6dc1f82
deps: remove archs/aix64-gcc
danbev Apr 9, 2022
8dc71f2
deps: remove aix-gcc architecture
danbev Apr 14, 2022
4abe987
deps: remove linux-ppc architecture
danbev Apr 14, 2022
2798929
deps: remove linux-ppc64 architecture
danbev Apr 14, 2022
1102922
deps: upgrade npm to 8.8.0
npm-robot Apr 28, 2022
37ca110
src: make --no-node-snapshot a per-process option
joyeecheung Apr 28, 2022
e15d22c
doc: initial version of security-model-strategy.md
mhdawson Apr 12, 2022
dab15f6
esm: graduate top-level-await to stable
aduh95 Apr 28, 2022
8f2b228
doc: record March 2022 security release steward
richardlau Apr 28, 2022
e313dc6
doc: http2.createServer `options` as optional
daeyeon Apr 28, 2022
227a45b
doc: remove legacy `-J` test.py option from BUILDING.md
LiviaMedeiros Apr 21, 2022
60e461c
doc: reword "test directory"
LiviaMedeiros Apr 21, 2022
e808366
src: turn SSL_CTX_new CHECK/segfault into JS exception
addaleax Apr 28, 2022
3c796f8
test: fix `parallel/test-dgram-udp6-link-local-address`
aduh95 Apr 28, 2022
a0638a2
esm: fix imports from non-file module
aduh95 Apr 29, 2022
4af0fbd
v8: export cpu_profiler_metadata_size in getHeapCodeStatistics
theanarkh Apr 29, 2022
fbda87d
test: simplify test-gc-{http-client,net}-*
lpinca Apr 19, 2022
8e0e576
test: add tests for extracting function name
cola119 May 1, 2022
718d11f
perf_hooks: return different functions in timerify
himself65 Apr 24, 2022
1e7479d
tools: update lint-md-dependencies
nodejs-github-bot May 1, 2022
bf9240a
worker: add hasRef() to MessagePort
RaisinTen May 2, 2022
2a4c826
deps: update undici to 5.1.1
targos May 2, 2022
f35f8a6
2022-05-03, Version 18.1.0 (Current)
targos May 2, 2022
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
Prev Previous commit
Next Next commit
test_runner: add initial CLI runner
This commit introduces an initial version of a CLI-based
test runner.

PR-URL: #42658
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
  • Loading branch information
cjihrig authored and targos committed Apr 28, 2022
commit 78a860ae58bf332e9a8562233703a4eb4724f0db
11 changes: 11 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,16 @@ minimum allocation from the secure heap. The minimum value is `2`.
The maximum value is the lesser of `--secure-heap` or `2147483647`.
The value given must be a power of two.

### `--test`

<!-- YAML
added: REPLACEME
-->

Starts the Node.js command line test runner. This flag cannot be combined with
`--check`, `--eval`, `--interactive`, or the inspector. See the documentation
on [running tests from the command line][] for more details.

### `--test-only`

<!-- YAML
Expand Down Expand Up @@ -2033,6 +2043,7 @@ $ node --max-old-space-size=1536 index.js
[jitless]: https://v8.dev/blog/jitless
[libuv threadpool documentation]: https://docs.libuv.org/en/latest/threadpool.html
[remote code execution]: https://www.owasp.org/index.php/Code_Injection
[running tests from the command line]: test.md#running-tests-from-the-command-line
[security warning]: #warning-binding-inspector-to-a-public-ipport-combination-is-insecure
[timezone IDs]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
[ways that `TZ` is handled in other environments]: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
63 changes: 63 additions & 0 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,67 @@ test('a test that creates asynchronous activity', (t) => {
});
```

## Running tests from the command line

The Node.js test runner can be invoked from the command line by passing the
[`--test`][] flag:

```bash
node --test
```

By default, Node.js will recursively search the current directory for
JavaScript source files matching a specific naming convention. Matching files
are executed as test files. More information on the expected test file naming
convention and behavior can be found in the [test runner execution model][]
section.

Alternatively, one or more paths can be provided as the final argument(s) to
the Node.js command, as shown below.

```bash
node --test test1.js test2.mjs custom_test_dir/
```

In this example, the test runner will execute the files `test1.js` and
`test2.mjs`. The test runner will also recursively search the
`custom_test_dir/` directory for test files to execute.

### Test runner execution model

When searching for test files to execute, the test runner behaves as follows:

* Any files explicitly provided by the user are executed.
* If the user did not explicitly specify any paths, the current working
directory is recursively searched for files as specified in the following
steps.
* `node_modules` directories are skipped unless explicitly provided by the
user.
* If a directory named `test` is encountered, the test runner will search it
recursively for all all `.js`, `.cjs`, and `.mjs` files. All of these files
are treated as test files, and do not need to match the specific naming
convention detailed below. This is to accommodate projects that place all of
their tests in a single `test` directory.
* In all other directories, `.js`, `.cjs`, and `.mjs` files matching the
following patterns are treated as test files:
* `^test$` - Files whose basename is the string `'test'`. Examples:
`test.js`, `test.cjs`, `test.mjs`.
* `^test-.+` - Files whose basename starts with the string `'test-'`
followed by one or more characters. Examples: `test-example.js`,
`test-another-example.mjs`.
* `.+[\.\-\_]test$` - Files whose basename ends with `.test`, `-test`, or
`_test`, preceded by one or more characters. Examples: `example.test.js`,
`example-test.cjs`, `example_test.mjs`.
* Other file types understood by Node.js such as `.node` and `.json` are not
automatically executed by the test runner, but are supported if explicitly
provided on the command line.

Each matching test file is executed in a separate child process. If the child
process finishes with an exit code of 0, the test is considered passing.
Otherwise, the test is considered to be a failure. Test files must be
executable by Node.js, but are not required to use the `node:test` module
internally.

## `test([name][, options][, fn])`

<!-- YAML
Expand Down Expand Up @@ -368,5 +429,7 @@ behaves in the same fashion as the top level [`test()`][] function.

[TAP]: https://testanything.org/
[`--test-only`]: cli.md#--test-only
[`--test`]: cli.md#--test
[`TestContext`]: #class-testcontext
[`test()`]: #testname-options-fn
[test runner execution model]: #test-runner-execution-model
3 changes: 3 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ the secure heap. The default is 0. The value must be a power of two.
.It Fl -secure-heap-min Ns = Ns Ar n
Specify the minimum allocation from the OpenSSL secure heap. The default is 2. The value must be a power of two.
.
.It Fl -test
Starts the Node.js command line test runner.
.
.It Fl -test-only
Configures the test runner to only execute top level tests that have the `only`
option set.
Expand Down
20 changes: 17 additions & 3 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ function isErrorStackTraceLimitWritable() {
desc.set !== undefined;
}

function inspectWithNoCustomRetry(obj, options) {
const utilInspect = lazyInternalUtilInspect();

try {
return utilInspect.inspect(obj, options);
} catch {
return utilInspect.inspect(obj, { ...options, customInspect: false });
}
}

// A specialized Error that includes an additional info property with
// additional information about the error condition.
// It has the properties present in a UVException but with a custom error
Expand Down Expand Up @@ -862,6 +872,7 @@ module.exports = {
getMessage,
hideInternalStackFrames,
hideStackFrames,
inspectWithNoCustomRetry,
isErrorStackTraceLimitWritable,
isStackOverflowError,
kEnhanceStackBeforeInspector,
Expand Down Expand Up @@ -1549,11 +1560,14 @@ E('ERR_TEST_FAILURE', function(error, failureType) {
assert(typeof failureType === 'string',
"The 'failureType' argument must be of type string.");

const msg = error?.message ?? lazyInternalUtilInspect().inspect(error);
let msg = error?.message ?? error;

this.failureType = error?.failureType ?? failureType;
this.cause = error;
if (typeof msg !== 'string') {
msg = inspectWithNoCustomRetry(msg);
}

this.failureType = failureType;
this.cause = error;
return msg;
}, Error);
E('ERR_TLS_CERT_ALTNAME_FORMAT', 'Invalid subject alternative name string',
Expand Down
157 changes: 157 additions & 0 deletions lib/internal/main/test_runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
'use strict';
const {
ArrayFrom,
ArrayPrototypeFilter,
ArrayPrototypeIncludes,
ArrayPrototypePush,
ArrayPrototypeSlice,
ArrayPrototypeSort,
Promise,
SafeSet,
} = primordials;
const {
prepareMainThreadExecution,
} = require('internal/bootstrap/pre_execution');
const { spawn } = require('child_process');
const { readdirSync, statSync } = require('fs');
const console = require('internal/console/global');
const {
codes: {
ERR_TEST_FAILURE,
},
} = require('internal/errors');
const test = require('internal/test_runner/harness');
const { kSubtestsFailed } = require('internal/test_runner/test');
const {
isSupportedFileType,
doesPathMatchFilter,
} = require('internal/test_runner/utils');
const { basename, join, resolve } = require('path');
const kFilterArgs = ['--test'];

prepareMainThreadExecution(false);
markBootstrapComplete();

// TODO(cjihrig): Replace this with recursive readdir once it lands.
function processPath(path, testFiles, options) {
const stats = statSync(path);

if (stats.isFile()) {
if (options.userSupplied ||
(options.underTestDir && isSupportedFileType(path)) ||
doesPathMatchFilter(path)) {
testFiles.add(path);
}
} else if (stats.isDirectory()) {
const name = basename(path);

if (!options.userSupplied && name === 'node_modules') {
return;
}

// 'test' directories get special treatment. Recursively add all .js,
// .cjs, and .mjs files in the 'test' directory.
const isTestDir = name === 'test';
const { underTestDir } = options;
const entries = readdirSync(path);

if (isTestDir) {
options.underTestDir = true;
}

options.userSupplied = false;

for (let i = 0; i < entries.length; i++) {
processPath(join(path, entries[i]), testFiles, options);
}

options.underTestDir = underTestDir;
}
}

function createTestFileList() {
const cwd = process.cwd();
const hasUserSuppliedPaths = process.argv.length > 1;
const testPaths = hasUserSuppliedPaths ?
ArrayPrototypeSlice(process.argv, 1) : [cwd];
const testFiles = new SafeSet();

try {
for (let i = 0; i < testPaths.length; i++) {
const absolutePath = resolve(testPaths[i]);

processPath(absolutePath, testFiles, { userSupplied: true });
}
} catch (err) {
if (err?.code === 'ENOENT') {
console.error(`Could not find '${err.path}'`);
process.exit(1);
}

throw err;
}

return ArrayPrototypeSort(ArrayFrom(testFiles));
}

function filterExecArgv(arg) {
return !ArrayPrototypeIncludes(kFilterArgs, arg);
}

function runTestFile(path) {
return test(path, () => {
return new Promise((resolve, reject) => {
const args = ArrayPrototypeFilter(process.execArgv, filterExecArgv);
ArrayPrototypePush(args, path);

const child = spawn(process.execPath, args);
// TODO(cjihrig): Implement a TAP parser to read the child's stdout
// instead of just displaying it all if the child fails.
let stdout = '';
let stderr = '';
let err;

child.on('error', (error) => {
err = error;
});

child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');

child.stdout.on('data', (chunk) => {
stdout += chunk;
});

child.stderr.on('data', (chunk) => {
stderr += chunk;
});

child.once('exit', (code, signal) => {
if (code !== 0 || signal !== null) {
if (!err) {
err = new ERR_TEST_FAILURE('test failed', kSubtestsFailed);
err.exitCode = code;
err.signal = signal;
err.stdout = stdout;
err.stderr = stderr;
// The stack will not be useful since the failures came from tests
// in a child process.
err.stack = undefined;
}

return reject(err);
}

resolve();
});
});
});
}

(async function main() {
const testFiles = createTestFileList();

for (let i = 0; i < testFiles.length; i++) {
runTestFile(testFiles[i]);
}
})();
Loading