| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 2a51f8b commit 56ce83b
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3438,6 +3438,10 @@ added: | |||
| 3438 | 3438 | - v18.9.0 | |
| 3439 | 3439 | - v16.19.0 | |
| 3440 | 3440 | changes: | |
| 3441 | + - version: REPLACEME | ||
| 3442 | + pr-url: https://github.com/nodejs/node/pull/64309 | ||
| 3443 | + description: Added `entryFile` to events forwarded from child processes | ||
| 3444 | + when tests run with process isolation. | ||
| 3441 | 3445 | - version: v26.3.0 | |
| 3442 | 3446 | pr-url: https://github.com/nodejs/node/pull/63435 | |
| 3443 | 3447 | description: Added `parentId` to test events that carry a `testId`. | |
@@ -3522,6 +3526,10 @@ Emitted when code coverage is enabled and all tests have completed. | |||
| 3522 | 3526 | * `cause` {Error} The actual error thrown by the test. | |
| 3523 | 3527 | * `type` {string|undefined} The type of the test, used to denote whether | |
| 3524 | 3528 | this is a suite. | |
| 3529 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3530 | + executed as the entry point of the child process that emitted this event. | ||
| 3531 | + Only present when tests run with process isolation. May differ from | ||
| 3532 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3525 | 3533 | * `file` {string|undefined} The path of the test file, | |
| 3526 | 3534 | `undefined` if test was run through the REPL. | |
| 3527 | 3535 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3551,6 +3559,10 @@ The corresponding declaration ordered events are `'test:pass'` and `'test:fail'` | |||
| 3551 | 3559 | * `data` {Object} | |
| 3552 | 3560 | * `column` {number|undefined} The column number where the test is defined, or | |
| 3553 | 3561 | `undefined` if the test was run through the REPL. | |
| 3562 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3563 | + executed as the entry point of the child process that emitted this event. | ||
| 3564 | + Only present when tests run with process isolation. May differ from | ||
| 3565 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3554 | 3566 | * `file` {string|undefined} The path of the test file, | |
| 3555 | 3567 | `undefined` if test was run through the REPL. | |
| 3556 | 3568 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3577,6 +3589,10 @@ defined. The corresponding declaration ordered event is `'test:start'`. | |||
| 3577 | 3589 | * `data` {Object} | |
| 3578 | 3590 | * `column` {number|undefined} The column number where the test is defined, or | |
| 3579 | 3591 | `undefined` if the test was run through the REPL. | |
| 3592 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3593 | + executed as the entry point of the child process that emitted this event. | ||
| 3594 | + Only present when tests run with process isolation. May differ from | ||
| 3595 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3580 | 3596 | * `file` {string|undefined} The path of the test file, | |
| 3581 | 3597 | `undefined` if test was run through the REPL. | |
| 3582 | 3598 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3598,6 +3614,10 @@ defined. | |||
| 3598 | 3614 | * `data` {Object} | |
| 3599 | 3615 | * `column` {number|undefined} The column number where the test is defined, or | |
| 3600 | 3616 | `undefined` if the test was run through the REPL. | |
| 3617 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3618 | + executed as the entry point of the child process that emitted this event. | ||
| 3619 | + Only present when tests run with process isolation. May differ from | ||
| 3620 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3601 | 3621 | * `file` {string|undefined} The path of the test file, | |
| 3602 | 3622 | `undefined` if test was run through the REPL. | |
| 3603 | 3623 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3630,6 +3650,10 @@ Emitted when a test is enqueued for execution. | |||
| 3630 | 3650 | this is a suite. | |
| 3631 | 3651 | * `attempt` {number|undefined} The attempt number of the test run, | |
| 3632 | 3652 | present only when using the [`--test-rerun-failures`][] flag. | |
| 3653 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3654 | + executed as the entry point of the child process that emitted this event. | ||
| 3655 | + Only present when tests run with process isolation. May differ from | ||
| 3656 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3633 | 3657 | * `file` {string|undefined} The path of the test file, | |
| 3634 | 3658 | `undefined` if test was run through the REPL. | |
| 3635 | 3659 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3693,6 +3717,10 @@ since the parent runner only knows about file-level tests. When using | |||
| 3693 | 3717 | present only when using the [`--test-rerun-failures`][] flag. | |
| 3694 | 3718 | * `passed_on_attempt` {number|undefined} The attempt number the test passed on, | |
| 3695 | 3719 | present only when using the [`--test-rerun-failures`][] flag. | |
| 3720 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3721 | + executed as the entry point of the child process that emitted this event. | ||
| 3722 | + Only present when tests run with process isolation. May differ from | ||
| 3723 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3696 | 3724 | * `file` {string|undefined} The path of the test file, | |
| 3697 | 3725 | `undefined` if test was run through the REPL. | |
| 3698 | 3726 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3722,6 +3750,10 @@ The corresponding execution ordered event is `'test:complete'`. | |||
| 3722 | 3750 | * `data` {Object} | |
| 3723 | 3751 | * `column` {number|undefined} The column number where the test is defined, or | |
| 3724 | 3752 | `undefined` if the test was run through the REPL. | |
| 3753 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3754 | + executed as the entry point of the child process that emitted this event. | ||
| 3755 | + Only present when tests run with process isolation. May differ from | ||
| 3756 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3725 | 3757 | * `file` {string|undefined} The path of the test file, | |
| 3726 | 3758 | `undefined` if test was run through the REPL. | |
| 3727 | 3759 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3738,6 +3770,10 @@ defined. | |||
| 3738 | 3770 | * `data` {Object} | |
| 3739 | 3771 | * `column` {number|undefined} The column number where the test is defined, or | |
| 3740 | 3772 | `undefined` if the test was run through the REPL. | |
| 3773 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3774 | + executed as the entry point of the child process that emitted this event. | ||
| 3775 | + Only present when tests run with process isolation. May differ from | ||
| 3776 | + `file` when the test is defined in a module imported by the entry file. | ||
| 3741 | 3777 | * `file` {string|undefined} The path of the test file, | |
| 3742 | 3778 | `undefined` if test was run through the REPL. | |
| 3743 | 3779 | * `line` {number|undefined} The line number where the test is defined, or | |
@@ -3762,6 +3798,9 @@ The corresponding execution ordered event is `'test:dequeue'`. | |||
| 3762 | 3798 | ### Event: `'test:stderr'` | |
| 3763 | 3799 | ||
| 3764 | 3800 | * `data` {Object} | |
| 3801 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3802 | + executed as the entry point of the child process that emitted this event. | ||
| 3803 | + Only present when tests run with process isolation. | ||
| 3765 | 3804 | * `file` {string} The path of the test file. | |
| 3766 | 3805 | * `message` {string} The message written to `stderr`. | |
| 3767 | 3806 | ||
@@ -3773,6 +3812,9 @@ defined. | |||
| 3773 | 3812 | ### Event: `'test:stdout'` | |
| 3774 | 3813 | ||
| 3775 | 3814 | * `data` {Object} | |
| 3815 | + * `entryFile` {string|undefined} The path of the test file that was | ||
| 3816 | + executed as the entry point of the child process that emitted this event. | ||
| 3817 | + Only present when tests run with process isolation. | ||
| 3776 | 3818 | * `file` {string} The path of the test file. | |
| 3777 | 3819 | * `message` {string} The message written to `stdout`. | |
| 3778 | 3820 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -295,6 +295,10 @@ class FileTest extends Test { | |||
| 295 | 295 | ArrayPrototypeIncludes(kDiagnosticsFilterArgs, StringPrototypeSlice(comment, 0, firstSpaceIndex)); | |
| 296 | 296 | } | |
| 297 | 297 | #handleReportItem(item) { | |
| 298 | + // The name is empty when a single child process runs all test files. | ||
| 299 | + if (this.name !== '') { | ||
| 300 | + item.data.entryFile = this.loc.file; | ||
| 301 | + } | ||
| 298 | 302 | const isTopLevel = item.data.nesting === 0; | |
| 299 | 303 | if (isTopLevel) { | |
| 300 | 304 | if (item.type === 'test:plan' && this.#skipReporting()) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + import { test } from 'node:test'; | ||
| 2 | + import { runShared } from './helper.mjs'; | ||
| 3 | + test('backup A', async (t) => { await runShared(t, 'A'); }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + import { test } from 'node:test'; | ||
| 2 | + import { runShared } from './helper.mjs'; | ||
| 3 | + test('backup B', async (t) => { await runShared(t, 'B'); }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + export async function runShared(t, target) { | ||
| 2 | + await t.test(`restore ${target}`, async () => {}); | ||
| 3 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,59 @@ | |||
| 1 | + import '../common/index.mjs'; | ||
| 2 | + import * as fixtures from '../common/fixtures.mjs'; | ||
| 3 | + import { describe, it, run } from 'node:test'; | ||
| 4 | + import assert from 'node:assert'; | ||
| 5 | + | ||
| 6 | + const aPath = fixtures.path('test-runner', 'entry-file', 'a.test.mjs'); | ||
| 7 | + const bPath = fixtures.path('test-runner', 'entry-file', 'b.test.mjs'); | ||
| 8 | + const helperPath = fixtures.path('test-runner', 'entry-file', 'helper.mjs'); | ||
| 9 | + | ||
| 10 | + async function collectEvents(options) { | ||
| 11 | + const events = []; | ||
| 12 | + const stream = run({ files: [aPath, bPath], ...options }); | ||
| 13 | + stream.on('test:fail', () => {}); | ||
| 14 | + for await (const event of stream) { | ||
| 15 | + events.push(event); | ||
| 16 | + } | ||
| 17 | + return events; | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + describe('entryFile attribution in reporter events', { concurrency: false }, () => { | ||
| 21 | + it('stamps entryFile on events forwarded from child processes', async () => { | ||
| 22 | + const events = await collectEvents({ isolation: 'process' }); | ||
| 23 | + const checked = { __proto__: null, A: 0, B: 0 }; | ||
| 24 | + | ||
| 25 | + for (const { type, data } of events) { | ||
| 26 | + if (data?.name === 'restore A' || data?.name === 'restore B') { | ||
| 27 | + const target = data.name === 'restore A' ? 'A' : 'B'; | ||
| 28 | + const expectedEntry = target === 'A' ? aPath : bPath; | ||
| 29 | + assert.strictEqual(data.file, helperPath, | ||
| 30 | + `${type} file should be the definition site`); | ||
| 31 | + assert.strictEqual(data.entryFile, expectedEntry, | ||
| 32 | + `${type} entryFile should be the entry file`); | ||
| 33 | + checked[target]++; | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + // Each subtest emits at least enqueue/dequeue/start/pass/complete. | ||
| 38 | + assert.ok(checked.A >= 4, `expected events for restore A, got ${checked.A}`); | ||
| 39 | + assert.ok(checked.B >= 4, `expected events for restore B, got ${checked.B}`); | ||
| 40 | + }); | ||
| 41 | + | ||
| 42 | + it('stamps entryFile on top-level tests forwarded from child processes', async () => { | ||
| 43 | + const events = await collectEvents({ isolation: 'process' }); | ||
| 44 | + const pass = events.filter(({ type }) => type === 'test:pass'); | ||
| 45 | + const backupA = pass.find(({ data }) => data.name === 'backup A'); | ||
| 46 | + const backupB = pass.find(({ data }) => data.name === 'backup B'); | ||
| 47 | + assert.strictEqual(backupA.data.entryFile, aPath); | ||
| 48 | + assert.strictEqual(backupB.data.entryFile, bPath); | ||
| 49 | + }); | ||
| 50 | + | ||
| 51 | + it('does not stamp entryFile with isolation none', async () => { | ||
| 52 | + const events = await collectEvents({ isolation: 'none' }); | ||
| 53 | + for (const { data } of events) { | ||
| 54 | + if (data?.name === 'restore A' || data?.name === 'restore B') { | ||
| 55 | + assert.strictEqual(data.entryFile, undefined); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + }); | ||
| 59 | + }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ import { describe, it, beforeEach } from 'node:test'; | |||
| 5 | 5 | import assert from 'node:assert'; | |
| 6 | 6 | import { finished } from 'node:stream/promises'; | |
| 7 | 7 | import { DefaultSerializer } from 'node:v8'; | |
| 8 | + import { resolve } from 'node:path'; | ||
| 8 | 9 | import serializer from 'internal/test_runner/reporter/v8-serializer'; | |
| 9 | 10 | import runner from 'internal/test_runner/runner'; | |
| 10 | 11 | ||
@@ -14,10 +15,15 @@ async function toArray(chunks) { | |||
| 14 | 15 | return arr; | |
| 15 | 16 | } | |
| 16 | 17 | ||
| 18 | + const entryFile = resolve('filetest'); | ||
| 17 | 19 | const diagnosticEvent = { | |
| 18 | 20 | type: 'test:diagnostic', | |
| 19 | 21 | data: { nesting: 0, details: {}, message: 'diagnostic' }, | |
| 20 | 22 | }; | |
| 23 | + const reportedDiagnosticEvent = { | ||
| 24 | + type: 'test:diagnostic', | ||
| 25 | + data: { ...diagnosticEvent.data, entryFile }, | ||
| 26 | + }; | ||
| 21 | 27 | const chunks = await toArray(serializer([diagnosticEvent])); | |
| 22 | 28 | const defaultSerializer = new DefaultSerializer(); | |
| 23 | 29 | defaultSerializer.writeHeader(); | |
@@ -67,28 +73,28 @@ describe('v8 deserializer', common.mustCall(() => { | |||
| 67 | 73 | it('should deserialize a chunk with no serialization', async () => { | |
| 68 | 74 | const reported = await collectReported([Buffer.from('unknown')]); | |
| 69 | 75 | assert.deepStrictEqual(reported, [ | |
| 70 | - { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 76 | + { data: { __proto__: null, entryFile, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 71 | 77 | ]); | |
| 72 | 78 | }); | |
| 73 | 79 | ||
| 74 | 80 | it('should deserialize a serialized chunk', async () => { | |
| 75 | 81 | const reported = await collectReported(chunks); | |
| 76 | - assert.deepStrictEqual(reported, [diagnosticEvent]); | ||
| 82 | + assert.deepStrictEqual(reported, [reportedDiagnosticEvent]); | ||
| 77 | 83 | }); | |
| 78 | 84 | ||
| 79 | 85 | it('should deserialize a serialized chunk after non-serialized chunk', async () => { | |
| 80 | 86 | const reported = await collectReported([Buffer.concat([Buffer.from('unknown'), ...chunks])]); | |
| 81 | 87 | assert.deepStrictEqual(reported, [ | |
| 82 | - { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 83 | - diagnosticEvent, | ||
| 88 | + { data: { __proto__: null, entryFile, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 89 | + reportedDiagnosticEvent, | ||
| 84 | 90 | ]); | |
| 85 | 91 | }); | |
| 86 | 92 | ||
| 87 | 93 | it('should deserialize a serialized chunk before non-serialized output', async () => { | |
| 88 | 94 | const reported = await collectReported([Buffer.concat([ ...chunks, Buffer.from('unknown')])]); | |
| 89 | 95 | assert.deepStrictEqual(reported, [ | |
| 90 | - diagnosticEvent, | ||
| 91 | - { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 96 | + reportedDiagnosticEvent, | ||
| 97 | + { data: { __proto__: null, entryFile, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 92 | 98 | ]); | |
| 93 | 99 | }); | |
| 94 | 100 | ||
@@ -131,7 +137,7 @@ describe('v8 deserializer', common.mustCall(() => { | |||
| 131 | 137 | oversizedLengthHeader, | |
| 132 | 138 | ...chunks, | |
| 133 | 139 | ]); | |
| 134 | - assert.deepStrictEqual(reported.at(-1), diagnosticEvent); | ||
| 140 | + assert.deepStrictEqual(reported.at(-1), reportedDiagnosticEvent); | ||
| 135 | 141 | assert.strictEqual(reported.filter((event) => event.type === 'test:diagnostic').length, 1); | |
| 136 | 142 | assert.strictEqual(collectStdout(reported), oversizedLengthStdout); | |
| 137 | 143 | }); | |
@@ -152,7 +158,7 @@ describe('v8 deserializer', common.mustCall(() => { | |||
| 152 | 158 | const data = chunks[0]; | |
| 153 | 159 | const reported = await collectReported([data.subarray(0, i), data.subarray(i)]); | |
| 154 | 160 | assert.deepStrictEqual(reported, [ | |
| 155 | - diagnosticEvent, | ||
| 161 | + reportedDiagnosticEvent, | ||
| 156 | 162 | ]); | |
| 157 | 163 | }); | |
| 158 | 164 | ||
@@ -163,9 +169,9 @@ describe('v8 deserializer', common.mustCall(() => { | |||
| 163 | 169 | Buffer.concat([data.subarray(i), Buffer.from('unknown')]), | |
| 164 | 170 | ]); | |
| 165 | 171 | assert.deepStrictEqual(reported, [ | |
| 166 | - { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 167 | - diagnosticEvent, | ||
| 168 | - { data: { __proto__: null, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 172 | + { data: { __proto__: null, entryFile, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 173 | + reportedDiagnosticEvent, | ||
| 174 | + { data: { __proto__: null, entryFile, file: 'filetest', message: 'unknown' }, type: 'test:stdout' }, | ||
| 169 | 175 | ]); | |
| 170 | 176 | } | |
| 171 | 177 | ); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments