mirror of
https://github.com/nodejs/node.git
synced 2025-05-03 20:29:36 +00:00

Add an v8.takeCoverage() API that allows the user to write the coverage started by NODE_V8_COVERAGE to disk on demand. The coverage can be written multiple times during the lifetime of the process, each time the execution counter will be reset. When the process is about to exit, one last coverage will still be written to disk. Also refactors the internal profiler connection code so that we use the inspector response id to identify the profile response instead of using an ad-hoc flag in C++. PR-URL: https://github.com/nodejs/node/pull/33807 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Jiawen Geng <technicalcute@gmail.com> Reviewed-By: Ben Coe <bencoe@gmail.com>
86 lines
2.8 KiB
JavaScript
86 lines
2.8 KiB
JavaScript
'use strict';
|
|
|
|
if (!process.features.inspector) return;
|
|
|
|
require('../common');
|
|
const fixtures = require('../common/fixtures');
|
|
const tmpdir = require('../common/tmpdir');
|
|
const assert = require('assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const { spawnSync } = require('child_process');
|
|
|
|
tmpdir.refresh();
|
|
const intervals = 40;
|
|
// Outputs coverage when v8.takeCoverage() is invoked.
|
|
{
|
|
const output = spawnSync(process.execPath, [
|
|
'-r',
|
|
fixtures.path('v8-coverage', 'take-coverage'),
|
|
fixtures.path('v8-coverage', 'interval'),
|
|
], {
|
|
env: {
|
|
...process.env,
|
|
NODE_V8_COVERAGE: tmpdir.path,
|
|
NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER',
|
|
TEST_INTERVALS: intervals
|
|
},
|
|
});
|
|
console.log(output.stderr.toString());
|
|
assert.strictEqual(output.status, 0);
|
|
const coverageFiles = fs.readdirSync(tmpdir.path);
|
|
|
|
let coverages = [];
|
|
for (const coverageFile of coverageFiles) {
|
|
const coverage = require(path.join(tmpdir.path, coverageFile));
|
|
for (const result of coverage.result) {
|
|
if (result.url.includes('/interval')) {
|
|
coverages.push({
|
|
file: coverageFile,
|
|
func: result.functions.find((f) => f.functionName === 'interval'),
|
|
timestamp: coverage.timestamp
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
coverages = coverages.sort((a, b) => { return a.timestamp - b.timestamp; });
|
|
// There should be two coverages taken, one triggered by v8.takeCoverage(),
|
|
// the other by process exit.
|
|
console.log('Coverages:', coverages);
|
|
assert.strictEqual(coverages.length, 3);
|
|
|
|
let blockHitsTotal = 0;
|
|
for (let i = 0; i < coverages.length; ++i) {
|
|
const { ranges } = coverages[i].func;
|
|
console.log('coverage', i, ranges);
|
|
|
|
if (i !== coverages.length - 1) {
|
|
// When the first two coverages are taken:
|
|
assert.strictEqual(ranges.length, 2);
|
|
const blockHits = ranges[0].count;
|
|
// The block inside interval() should be hit at least once.
|
|
assert.notStrictEqual(blockHits, 0);
|
|
blockHitsTotal += blockHits;
|
|
// The else branch should not be hit.
|
|
const elseBranchHits = ranges[1].count;
|
|
assert.strictEqual(elseBranchHits, 0);
|
|
} else {
|
|
// At process exit:
|
|
assert.strictEqual(ranges.length, 3);
|
|
const blockHits = ranges[0].count;
|
|
// The block inside interval() should be hit at least once more.
|
|
assert.notStrictEqual(blockHits, 0);
|
|
blockHitsTotal += blockHits;
|
|
// The else branch should be hit exactly once.
|
|
const elseBranchHits = ranges[2].count;
|
|
assert.strictEqual(elseBranchHits, 1);
|
|
const ifBranchHits = ranges[1].count;
|
|
assert.strictEqual(ifBranchHits, blockHits - elseBranchHits);
|
|
}
|
|
}
|
|
|
|
// The block should be hit `intervals` times in total.
|
|
assert.strictEqual(blockHitsTotal, intervals);
|
|
}
|