Skip to content

Commit 4b39649

Browse files
committed
test_runner: improve code coverage cleanup
The test runner's code coverage leaves old coverage data in the temp directory. This commit updates the cleanup logic to: - Stop code collection. Otherwise V8 would write collection data again when the process exits. - Remove the temp directory containing the coverage data. - Attempt to clean up the coverage data even if parsing the data resulted in an error. With this change, I no longer see any coverage data left behind in the system temp directory. Refs: nodejs/build#3864 Refs: nodejs/build#3887
1 parent 9404d3a commit 4b39649

File tree

3 files changed

+48
-20
lines changed

3 files changed

+48
-20
lines changed

Diff for: lib/internal/test_runner/coverage.js

+24-16
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
mkdtempSync,
2424
opendirSync,
2525
readFileSync,
26+
rmSync,
2627
} = require('fs');
2728
const { setupCoverageHooks } = require('internal/util');
2829
const { tmpdir } = require('os');
@@ -272,28 +273,35 @@ class TestCoverage {
272273
cleanup() {
273274
// Restore the original value of process.env.NODE_V8_COVERAGE. Then, copy
274275
// all of the created coverage files to the original coverage directory.
276+
internalBinding('profiler').endCoverage();
277+
275278
if (this.originalCoverageDirectory === undefined) {
276279
delete process.env.NODE_V8_COVERAGE;
277-
return;
278-
}
279-
280-
process.env.NODE_V8_COVERAGE = this.originalCoverageDirectory;
281-
let dir;
280+
} else {
281+
process.env.NODE_V8_COVERAGE = this.originalCoverageDirectory;
282+
let dir;
282283

283-
try {
284-
mkdirSync(this.originalCoverageDirectory, { __proto__: null, recursive: true });
285-
dir = opendirSync(this.coverageDirectory);
284+
try {
285+
mkdirSync(this.originalCoverageDirectory, { __proto__: null, recursive: true });
286+
dir = opendirSync(this.coverageDirectory);
286287

287-
for (let entry; (entry = dir.readSync()) !== null;) {
288-
const src = join(this.coverageDirectory, entry.name);
289-
const dst = join(this.originalCoverageDirectory, entry.name);
290-
copyFileSync(src, dst);
291-
}
292-
} finally {
293-
if (dir) {
294-
dir.closeSync();
288+
for (let entry; (entry = dir.readSync()) !== null;) {
289+
const src = join(this.coverageDirectory, entry.name);
290+
const dst = join(this.originalCoverageDirectory, entry.name);
291+
copyFileSync(src, dst);
292+
}
293+
} finally {
294+
if (dir) {
295+
dir.closeSync();
296+
}
295297
}
296298
}
299+
300+
try {
301+
rmSync(this.coverageDirectory, { __proto__: null, recursive: true });
302+
} catch {
303+
// Ignore cleanup errors.
304+
}
297305
}
298306

299307
getCoverageFromDirectory() {

Diff for: lib/internal/test_runner/harness.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,15 @@ function collectCoverage(rootTest, coverage) {
159159

160160
try {
161161
summary = coverage.summary();
162-
coverage.cleanup();
163162
} catch (err) {
164-
const op = summary ? 'clean up' : 'report';
165-
const msg = `Warning: Could not ${op} code coverage. ${err}`;
163+
rootTest.diagnostic(`Warning: Could not report code coverage. ${err}`);
164+
process.exitCode = kGenericUserError;
165+
}
166166

167-
rootTest.diagnostic(msg);
167+
try {
168+
coverage.cleanup();
169+
} catch (err) {
170+
rootTest.diagnostic(`Warning: Could not clean up code coverage. ${err}`);
168171
process.exitCode = kGenericUserError;
169172
}
170173

Diff for: src/inspector_profiler.cc

+17
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,21 @@ static void StopCoverage(const FunctionCallbackInfo<Value>& args) {
556556
}
557557
}
558558

559+
static void EndCoverage(const FunctionCallbackInfo<Value>& args) {
560+
Environment* env = Environment::GetCurrent(args);
561+
V8CoverageConnection* connection = env->coverage_connection();
562+
563+
Debug(env,
564+
DebugCategory::INSPECTOR_PROFILER,
565+
"EndCoverage, connection %s nullptr\n",
566+
connection == nullptr ? "==" : "!=");
567+
568+
if (connection != nullptr) {
569+
Debug(env, DebugCategory::INSPECTOR_PROFILER, "Ending coverage\n");
570+
connection->End();
571+
}
572+
}
573+
559574
static void Initialize(Local<Object> target,
560575
Local<Value> unused,
561576
Local<Context> context,
@@ -565,13 +580,15 @@ static void Initialize(Local<Object> target,
565580
context, target, "setSourceMapCacheGetter", SetSourceMapCacheGetter);
566581
SetMethod(context, target, "takeCoverage", TakeCoverage);
567582
SetMethod(context, target, "stopCoverage", StopCoverage);
583+
SetMethod(context, target, "endCoverage", EndCoverage);
568584
}
569585

570586
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
571587
registry->Register(SetCoverageDirectory);
572588
registry->Register(SetSourceMapCacheGetter);
573589
registry->Register(TakeCoverage);
574590
registry->Register(StopCoverage);
591+
registry->Register(EndCoverage);
575592
}
576593

577594
} // namespace profiler

0 commit comments

Comments
 (0)