Skip to content

Commit cd45963

Browse files
committed
test: migrate test runner message tests to snapshot
1 parent a00137e commit cd45963

37 files changed

+432
-318
lines changed

β€Žtest/common/README.md

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

645+
### `NODE_REGENERATE_SHANPSHOTS`
646+
647+
If set, test snapshots are regenerated.
648+
645649
### `NODE_SKIP_FLAG_CHECK`
646650

647651
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
@@ -60,6 +60,31 @@ const hasOpenSSL3 = hasCrypto &&
6060

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

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

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
const expected = process.env.NODE_REGENERATE_SHANPSHOTS ? actual : await fs.readFile(snapshot, 'utf8');
26+
if (process.env.NODE_REGENERATE_SHANPSHOTS) {
27+
await fs.writeFile(snapshot, actual);
28+
}
29+
assert.strictEqual(actual, expected);
30+
}
31+
32+
async function spawnAndAssert(filename, transform = (x) => x) {
33+
const flags = common.parseTestFlags(filename);
34+
const { stderr, stdout } = await common.spawnPromisified(process.execPath, [...flags, filename]);
35+
await assertSnapshot(transform(`${stdout}${stderr}`), filename);
36+
}
37+
38+
module.exports = {
39+
assertSnapshot,
40+
getSnapshotPath,
41+
replaceStackTrace,
42+
spawnAndAssert,
43+
transform,
44+
};

β€Ž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)