Skip to content

Commit e8250c8

Browse files
committed
test_runner: dont buffer unordered events in process isolation mode
Signed-off-by: Moshe Atlow <moshe@atlow.co.il>
1 parent 59e8484 commit e8250c8

4 files changed

Lines changed: 91 additions & 0 deletions

File tree

lib/internal/test_runner/runner.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ const kDiagnosticsFilterArgs = ['tests', 'suites', 'pass', 'fail', 'cancelled',
128128
const kCanceledTests = new SafeSet()
129129
.add(kCancelledByParent).add(kAborted).add(kTestTimeoutFailure);
130130

131+
// Execution-ordered events are forwarded immediately, bypassing the
132+
// per-file declaration-order buffer.
133+
const kExecutionOrderedEvents = new SafeSet()
134+
.add('test:enqueue').add('test:dequeue').add('test:complete');
135+
131136
let kResistStopPropagation;
132137

133138
// Worker ID pool management for concurrent test execution
@@ -331,6 +336,10 @@ class FileTest extends Test {
331336
}
332337
}
333338
addToReport(item) {
339+
if (kExecutionOrderedEvents.has(item.type)) {
340+
this.#handleReportItem(item);
341+
return;
342+
}
334343
this.#accumulateReportItem(item);
335344
if (!this.isClearToSend()) {
336345
ArrayPrototypePush(this.#reportBuffer, item);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { test } from 'node:test';
2+
import assert from 'node:assert';
3+
4+
test('fast-fail', () => {
5+
assert.fail('fast');
6+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test } from 'node:test';
2+
import { setTimeout as sleep } from 'node:timers/promises';
3+
import { existsSync } from 'node:fs';
4+
5+
test('slow', async () => {
6+
const goFile = process.env.NODE_TEST_GO_FILE;
7+
for (let i = 0; i < 200; i++) {
8+
if (existsSync(goFile)) return;
9+
await sleep(50);
10+
}
11+
throw new Error('go signal from host never arrived');
12+
});
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Flags: --no-warnings
2+
3+
import '../common/index.mjs';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
import tmpdir from '../common/tmpdir.js';
6+
import assert from 'node:assert';
7+
import { writeFileSync } from 'node:fs';
8+
import { test, run } from 'node:test';
9+
10+
const files = [
11+
fixtures.path('test-runner', 'execution-ordered-bypass', 'slow.mjs'),
12+
fixtures.path('test-runner', 'execution-ordered-bypass', 'fast-fail.mjs'),
13+
];
14+
15+
test('execution-ordered events bypass FileTest declaration-order buffer', async () => {
16+
tmpdir.refresh();
17+
const goFile = tmpdir.resolve('execution-ordered-go');
18+
19+
const stream = run({
20+
files,
21+
isolation: 'process',
22+
concurrency: true,
23+
env: { ...process.env, NODE_TEST_GO_FILE: goFile },
24+
});
25+
26+
const events = [];
27+
28+
stream.on('test:complete', (data) => {
29+
if (data.name === 'slow' || data.name === 'fast-fail') {
30+
events.push(`complete:${data.name}`);
31+
if (data.name === 'fast-fail') {
32+
writeFileSync(goFile, '');
33+
}
34+
}
35+
});
36+
37+
stream.on('test:fail', (data) => {
38+
if (data.name === 'fast-fail') {
39+
events.push(`fail:${data.name}`);
40+
}
41+
});
42+
43+
// eslint-disable-next-line no-unused-vars
44+
for await (const _ of stream);
45+
46+
const completeFast = events.indexOf('complete:fast-fail');
47+
const completeSlow = events.indexOf('complete:slow');
48+
const failFast = events.indexOf('fail:fast-fail');
49+
50+
assert.notStrictEqual(completeFast, -1);
51+
assert.notStrictEqual(completeSlow, -1);
52+
assert.notStrictEqual(failFast, -1);
53+
54+
assert.ok(
55+
completeFast < completeSlow,
56+
`test:complete for fast-fail should arrive before slow; events=${events.join(', ')}`,
57+
);
58+
59+
// test:fail is declaration-ordered, so the bypass must not affect it.
60+
assert.ok(
61+
failFast > completeSlow,
62+
`test:fail for fast-fail should arrive after test:complete for slow; events=${events.join(', ')}`,
63+
);
64+
});

0 commit comments

Comments
 (0)