Skip to content

Commit eef9e86

Browse files
committed
test: migrate test runner message tests to snapshot
1 parent 1cda3f3 commit eef9e86

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+452
-331
lines changed

β€Ž.github/CODEOWNERS

-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@
135135

136136
# Test runner
137137

138-
/test/message/test_runner_* @nodejs/test_runner
139138
/test/parallel/test-runner-* @nodejs/test_runner
140139
/doc/api/test.md @nodejs/test_runner
141140
/lib/test.js @nodejs/test_runner

β€Žtest/common/README.md

+6
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,12 @@ environment variables.
642642
If set, `NODE_COMMON_PORT`'s value overrides the `common.PORT` default value of
643643
12346\.
644644

645+
### `NODE_REGENERATE_SNAPSHOTS`
646+
647+
If set, test snapshots for a the current test are regenerated.
648+
for example `NODE_REGENERATE_SNAPSHOTS=1 out/Release/node test/parallel/test-runner-output.mjs`
649+
will update all the test runner output snapshots.
650+
645651
### `NODE_SKIP_FLAG_CHECK`
646652

647653
If set, command line arguments passed to individual tests are not validated.

β€Žtest/common/index.js

+45-38
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,31 @@ const hasOpenSSL3 = hasCrypto &&
6161

6262
const hasQuic = hasCrypto && !!process.config.variables.openssl_quic;
6363

64+
function parseTestFlags(filename = process.argv[1]) {
65+
// The copyright notice is relatively big and the flags could come afterwards.
66+
const bytesToRead = 1500;
67+
const buffer = Buffer.allocUnsafe(bytesToRead);
68+
const fd = fs.openSync(filename, 'r');
69+
const bytesRead = fs.readSync(fd, buffer, 0, bytesToRead);
70+
fs.closeSync(fd);
71+
const source = buffer.toString('utf8', 0, bytesRead);
72+
73+
const flagStart = source.indexOf('// Flags: --') + 10;
74+
75+
if (flagStart === 9) {
76+
return [];
77+
}
78+
let flagEnd = source.indexOf('\n', flagStart);
79+
// Normalize different EOL.
80+
if (source[flagEnd - 1] === '\r') {
81+
flagEnd--;
82+
}
83+
return source
84+
.substring(flagStart, flagEnd)
85+
.replace(/_/g, '-')
86+
.split(' ');
87+
}
88+
6489
// Check for flags. Skip this for workers (both, the `cluster` module and
6590
// `worker_threads`) and child processes.
6691
// If the binary was built without-ssl then the crypto flags are
@@ -71,44 +96,25 @@ if (process.argv.length === 2 &&
7196
hasCrypto &&
7297
require('cluster').isPrimary &&
7398
fs.existsSync(process.argv[1])) {
74-
// The copyright notice is relatively big and the flags could come afterwards.
75-
const bytesToRead = 1500;
76-
const buffer = Buffer.allocUnsafe(bytesToRead);
77-
const fd = fs.openSync(process.argv[1], 'r');
78-
const bytesRead = fs.readSync(fd, buffer, 0, bytesToRead);
79-
fs.closeSync(fd);
80-
const source = buffer.toString('utf8', 0, bytesRead);
81-
82-
const flagStart = source.indexOf('// Flags: --') + 10;
83-
if (flagStart !== 9) {
84-
let flagEnd = source.indexOf('\n', flagStart);
85-
// Normalize different EOL.
86-
if (source[flagEnd - 1] === '\r') {
87-
flagEnd--;
88-
}
89-
const flags = source
90-
.substring(flagStart, flagEnd)
91-
.replace(/_/g, '-')
92-
.split(' ');
93-
const args = process.execArgv.map((arg) => arg.replace(/_/g, '-'));
94-
for (const flag of flags) {
95-
if (!args.includes(flag) &&
96-
// If the binary is build without `intl` the inspect option is
97-
// invalid. The test itself should handle this case.
98-
(process.features.inspector || !flag.startsWith('--inspect'))) {
99-
console.log(
100-
'NOTE: The test started as a child_process using these flags:',
101-
inspect(flags),
102-
'Use NODE_SKIP_FLAG_CHECK to run the test with the original flags.',
103-
);
104-
const args = [...flags, ...process.execArgv, ...process.argv.slice(1)];
105-
const options = { encoding: 'utf8', stdio: 'inherit' };
106-
const result = spawnSync(process.execPath, args, options);
107-
if (result.signal) {
108-
process.kill(0, result.signal);
109-
} else {
110-
process.exit(result.status);
111-
}
99+
const flags = parseTestFlags();
100+
const args = process.execArgv.map((arg) => arg.replace(/_/g, '-'));
101+
for (const flag of flags) {
102+
if (!args.includes(flag) &&
103+
// If the binary is build without `intl` the inspect option is
104+
// invalid. The test itself should handle this case.
105+
(process.features.inspector || !flag.startsWith('--inspect'))) {
106+
console.log(
107+
'NOTE: The test started as a child_process using these flags:',
108+
inspect(flags),
109+
'Use NODE_SKIP_FLAG_CHECK to run the test with the original flags.',
110+
);
111+
const args = [...flags, ...process.execArgv, ...process.argv.slice(1)];
112+
const options = { encoding: 'utf8', stdio: 'inherit' };
113+
const result = spawnSync(process.execPath, args, options);
114+
if (result.signal) {
115+
process.kill(0, result.signal);
116+
} else {
117+
process.exit(result.status);
112118
}
113119
}
114120
}
@@ -929,6 +935,7 @@ const common = {
929935
mustSucceed,
930936
nodeProcessAborted,
931937
PIPE,
938+
parseTestFlags,
932939
platformTimeout,
933940
printSkipMessage,
934941
pwdCommand,

β€Žtest/common/index.mjs

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const {
3737
getCallSite,
3838
mustNotCall,
3939
mustNotMutateObjectDeep,
40+
parseTestFlags,
4041
printSkipMessage,
4142
skip,
4243
nodeProcessAborted,
@@ -88,6 +89,7 @@ export {
8889
getCallSite,
8990
mustNotCall,
9091
mustNotMutateObjectDeep,
92+
parseTestFlags,
9193
printSkipMessage,
9294
skip,
9395
nodeProcessAborted,

β€Žtest/common/snap.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
const common = require('./');
3+
const path = require('node:path');
4+
const fs = require('node:fs/promises');
5+
const assert = require('node:assert/strict');
6+
7+
8+
const stackFramesRegexp = /(\s+)((.+?)\s+\()?(?:\(?(.+?):(\d+)(?::(\d+))?)\)?(\s+\{)?(\n|$)/g;
9+
10+
function replaceStackTrace(str) {
11+
return str.replace(stackFramesRegexp, '$1*$7\n');
12+
}
13+
14+
function transform(...args) {
15+
return (str) => args.reduce((acc, fn) => fn(acc), str);
16+
}
17+
18+
function getSnapshotPath(filename) {
19+
const { name, dir } = path.parse(filename);
20+
return path.resolve(dir, `${name}.snapshot`);
21+
}
22+
23+
async function assertSnapshot(actual, filename = process.argv[1]) {
24+
const snapshot = getSnapshotPath(filename);
25+
if (process.env.NODE_REGENERATE_SNAPSHOTS) {
26+
await fs.writeFile(snapshot, actual);
27+
} else {
28+
const expected = await fs.readFile(snapshot, 'utf8');
29+
assert.strictEqual(actual, expected);
30+
}
31+
}
32+
33+
async function spawnAndAssert(filename, transform = (x) => x) {
34+
// TODO: Assert stderr as well.
35+
const flags = common.parseTestFlags(filename);
36+
const { stdout } = await common.spawnPromisified(process.execPath, [...flags, filename]);
37+
await assertSnapshot(transform(stdout), filename);
38+
}
39+
40+
module.exports = {
41+
assertSnapshot,
42+
getSnapshotPath,
43+
replaceStackTrace,
44+
spawnAndAssert,
45+
transform,
46+
};

β€Žtest/message/test_runner_abort.js β€Žtest/fixtures/test-runner/output/abort.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Flags: --no-warnings
22
'use strict';
3-
require('../common');
3+
require('../../../common');
44
const test = require('node:test');
55

66
test('promise timeout signal', { signal: AbortSignal.timeout(1) }, async (t) => {

β€Žtest/message/test_runner_abort.out β€Žtest/fixtures/test-runner/output/abort.snapshot

+8-8
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ TAP version 13
3131
# Subtest: not ok 2
3232
not ok 6 - not ok 2
3333
---
34-
duration_ms: *
34+
duration_ms: ZERO
3535
failureType: 'cancelledByParent'
3636
error: 'test did not finish before its parent and was cancelled'
3737
code: 'ERR_TEST_FAILURE'
3838
...
3939
# Subtest: not ok 3
4040
not ok 7 - not ok 3
4141
---
42-
duration_ms: *
42+
duration_ms: ZERO
4343
failureType: 'testAborted'
4444
error: 'This operation was aborted'
4545
code: 20
@@ -59,7 +59,7 @@ TAP version 13
5959
# Subtest: not ok 4
6060
not ok 8 - not ok 4
6161
---
62-
duration_ms: *
62+
duration_ms: ZERO
6363
failureType: 'testAborted'
6464
error: 'This operation was aborted'
6565
code: 20
@@ -79,7 +79,7 @@ TAP version 13
7979
# Subtest: not ok 5
8080
not ok 9 - not ok 5
8181
---
82-
duration_ms: *
82+
duration_ms: ZERO
8383
failureType: 'testAborted'
8484
error: 'This operation was aborted'
8585
code: 20
@@ -161,15 +161,15 @@ not ok 2 - promise abort signal
161161
# Subtest: not ok 2
162162
not ok 6 - not ok 2
163163
---
164-
duration_ms: *
164+
duration_ms: ZERO
165165
failureType: 'cancelledByParent'
166166
error: 'test did not finish before its parent and was cancelled'
167167
code: 'ERR_TEST_FAILURE'
168168
...
169169
# Subtest: not ok 3
170170
not ok 7 - not ok 3
171171
---
172-
duration_ms: *
172+
duration_ms: ZERO
173173
failureType: 'testAborted'
174174
error: 'This operation was aborted'
175175
code: 20
@@ -189,7 +189,7 @@ not ok 2 - promise abort signal
189189
# Subtest: not ok 4
190190
not ok 8 - not ok 4
191191
---
192-
duration_ms: *
192+
duration_ms: ZERO
193193
failureType: 'testAborted'
194194
error: 'This operation was aborted'
195195
code: 20
@@ -209,7 +209,7 @@ not ok 2 - promise abort signal
209209
# Subtest: not ok 5
210210
not ok 9 - not ok 5
211211
---
212-
duration_ms: *
212+
duration_ms: ZERO
213213
failureType: 'testAborted'
214214
error: 'This operation was aborted'
215215
code: 20

β€Žtest/message/test_runner_abort_suite.js β€Žtest/fixtures/test-runner/output/abort_suite.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Flags: --no-warnings
22
'use strict';
3-
require('../common');
3+
require('../../../common');
44
const { describe, it } = require('node:test');
55

66
describe('describe timeout signal', { signal: AbortSignal.timeout(1) }, (t) => {

β€Žtest/message/test_runner_abort_suite.out β€Žtest/fixtures/test-runner/output/abort_suite.snapshot

+4-4
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,31 @@ TAP version 13
3131
# Subtest: not ok 2
3232
not ok 6 - not ok 2
3333
---
34-
duration_ms: *
34+
duration_ms: ZERO
3535
failureType: 'cancelledByParent'
3636
error: 'test did not finish before its parent and was cancelled'
3737
code: 'ERR_TEST_FAILURE'
3838
...
3939
# Subtest: not ok 3
4040
not ok 7 - not ok 3
4141
---
42-
duration_ms: *
42+
duration_ms: ZERO
4343
failureType: 'cancelledByParent'
4444
error: 'test did not finish before its parent and was cancelled'
4545
code: 'ERR_TEST_FAILURE'
4646
...
4747
# Subtest: not ok 4
4848
not ok 8 - not ok 4
4949
---
50-
duration_ms: *
50+
duration_ms: ZERO
5151
failureType: 'cancelledByParent'
5252
error: 'test did not finish before its parent and was cancelled'
5353
code: 'ERR_TEST_FAILURE'
5454
...
5555
# Subtest: not ok 5
5656
not ok 9 - not ok 5
5757
---
58-
duration_ms: *
58+
duration_ms: ZERO
5959
failureType: 'cancelledByParent'
6060
error: 'test did not finish before its parent and was cancelled'
6161
code: 'ERR_TEST_FAILURE'

β€Žtest/message/test_runner_describe_it.js β€Žtest/fixtures/test-runner/output/describe_it.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Flags: --no-warnings
22
'use strict';
3-
require('../common');
3+
require('../../../common');
44
const assert = require('node:assert');
55
const { describe, it, test } = require('node:test');
66
const util = require('util');

β€Žtest/message/test_runner_describe_it.out β€Žtest/fixtures/test-runner/output/describe_it.snapshot

+7-7
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ ok 21 - immediate resolve pass
196196
*
197197
*
198198
*
199+
new Promise (<anonymous>)
199200
*
200201
*
201-
*
202-
*
202+
Array.map (<anonymous>)
203203
...
204204
# Subtest: mixing describe/it and test should work
205205
ok 2 - mixing describe/it and test should work
@@ -469,10 +469,10 @@ not ok 53 - custom inspect symbol that throws fail
469469
*
470470
*
471471
*
472+
new Promise (<anonymous>)
472473
*
473474
*
474-
*
475-
*
475+
Array.map (<anonymous>)
476476
...
477477
# Subtest: sync throw fails at second
478478
not ok 2 - sync throw fails at second
@@ -491,7 +491,7 @@ not ok 53 - custom inspect symbol that throws fail
491491
*
492492
*
493493
*
494-
*
494+
async Promise.all (index 0)
495495
...
496496
1..2
497497
not ok 54 - subtest sync throw fails
@@ -506,7 +506,7 @@ not ok 54 - subtest sync throw fails
506506
# Subtest: should not run
507507
not ok 1 - should not run
508508
---
509-
duration_ms: *
509+
duration_ms: ZERO
510510
failureType: 'cancelledByParent'
511511
error: 'test did not finish before its parent and was cancelled'
512512
code: 'ERR_TEST_FAILURE'
@@ -535,7 +535,7 @@ not ok 55 - describe sync throw fails
535535
# Subtest: should not run
536536
not ok 1 - should not run
537537
---
538-
duration_ms: *
538+
duration_ms: ZERO
539539
failureType: 'cancelledByParent'
540540
error: 'test did not finish before its parent and was cancelled'
541541
code: 'ERR_TEST_FAILURE'

β€Žtest/message/test_runner_describe_nested.js β€Žtest/fixtures/test-runner/output/describe_nested.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Flags: --no-warnings
22
'use strict';
3-
require('../common');
3+
require('../../../common');
44
const { describe, it } = require('node:test');
55

66
describe('nested - no tests', () => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Flags: --no-warnings
2+
'use strict';
3+
require('../../../common');
4+
const fixtures = require('../../../common/fixtures');
5+
const spawn = require('node:child_process').spawn;
6+
7+
spawn(process.execPath,
8+
['--no-warnings', '--test-reporter', 'dot', fixtures.path('test-runner/output/output.js')], { stdio: 'inherit' });

β€Žtest/message/test_runner_hooks.js β€Žtest/fixtures/test-runner/output/hooks.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Flags: --no-warnings
22
'use strict';
3-
const common = require('../common');
3+
const common = require('../../../common');
44
const assert = require('assert');
55
const { test, describe, it, before, after, beforeEach, afterEach } = require('node:test');
66

0 commit comments

Comments
Β (0)