mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Add a `startCoverage` method on the `profiler` internal binding so that V8 precise coverage can be enabled after bootstrap. The method is idempotent against the existing bootstrap path (which creates a V8CoverageConnection when NODE_V8_COVERAGE or --experimental-test-coverage is set) and a no-op when the inspector is unavailable, e.g. in the parent process of `--test --test-isolation=process` where workers handle coverage and Environment::should_create_inspector() returns false. Refs: https://github.com/nodejs/node/issues/60023 Signed-off-by: sangwook <rewq5991@gmail.com> PR-URL: https://github.com/nodejs/node/pull/63079 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com> Reviewed-By: Aviv Keller <me@aviv.sh>
72 lines
2.4 KiB
JavaScript
72 lines
2.4 KiB
JavaScript
import * as common from '../common/index.mjs';
|
|
import { before, describe, it, run } from 'node:test';
|
|
import assert from 'node:assert';
|
|
import { spawnSync } from 'node:child_process';
|
|
import { cp } from 'node:fs/promises';
|
|
import { join, sep } from 'node:path';
|
|
import tmpdir from '../common/tmpdir.js';
|
|
import fixtures from '../common/fixtures.js';
|
|
|
|
const skipIfNoInspector = {
|
|
skip: !process.features.inspector ? 'inspector disabled' : false,
|
|
};
|
|
|
|
tmpdir.refresh();
|
|
|
|
async function setupFixtures() {
|
|
const fixtureDir = fixtures.path('test-runner', 'coverage-isolation-none');
|
|
await cp(fixtureDir, tmpdir.path, { recursive: true });
|
|
}
|
|
|
|
describe('run() coverage with isolation: none', skipIfNoInspector, () => {
|
|
before(async () => {
|
|
await setupFixtures();
|
|
});
|
|
|
|
for (const isolation of ['none', 'process']) {
|
|
it(`reports src coverage and excludes test files by default (isolation=${isolation})`, async () => {
|
|
const stream = run({
|
|
files: [join(tmpdir.path, 'tests', 'foo.test.mjs')],
|
|
coverage: true,
|
|
isolation,
|
|
cwd: tmpdir.path,
|
|
});
|
|
stream.on('test:fail', common.mustNotCall());
|
|
|
|
let summary;
|
|
stream.on('test:coverage', common.mustCall(({ summary: s }) => {
|
|
summary = s;
|
|
}));
|
|
// eslint-disable-next-line no-unused-vars
|
|
for await (const _ of stream);
|
|
|
|
assert.ok(summary, 'test:coverage event must fire');
|
|
const paths = summary.files.map((f) => f.path);
|
|
assert.ok(
|
|
paths.length > 0,
|
|
`coverage files must be reported (isolation=${isolation}); got ${JSON.stringify(paths)}`,
|
|
);
|
|
assert.ok(
|
|
paths.some((p) => p.endsWith(`src${sep}foo.mjs`)),
|
|
`expected src/foo.mjs to be present (isolation=${isolation}); got ${JSON.stringify(paths)}`,
|
|
);
|
|
assert.ok(
|
|
paths.every((p) => !p.endsWith('foo.test.mjs')),
|
|
`expected foo.test.mjs to be excluded by default (isolation=${isolation}); got ${JSON.stringify(paths)}`,
|
|
);
|
|
});
|
|
}
|
|
|
|
it('is idempotent when --experimental-test-coverage is also passed', async () => {
|
|
const result = spawnSync(process.execPath, [
|
|
'--experimental-test-coverage',
|
|
join(tmpdir.path, 'runner.mjs'),
|
|
], { cwd: tmpdir.path });
|
|
assert.strictEqual(
|
|
result.status,
|
|
0,
|
|
`exited with ${result.status}\nstderr: ${result.stderr}\nstdout: ${result.stdout}`,
|
|
);
|
|
});
|
|
});
|