'use strict'; if (!process.features.inspector) return; const common = require('../common'); const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { spawnSync } = require('child_process'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); let dirc = 0; function nextdir() { return `cov_${++dirc}`; } // Outputs coverage when event loop is drained, with no async logic. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/basic') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('basic.js', coverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); } // Outputs coverage when error is thrown in first tick. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/throw') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 1) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 1); const fixtureCoverage = getFixtureCoverage('throw.js', coverageDirectory); assert.ok(fixtureCoverage, 'coverage not found for file'); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); } // Outputs coverage when process.exit(1) exits process. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/exit-1') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 1) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 1); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('exit-1.js', coverageDirectory); assert.ok(fixtureCoverage, 'coverage not found for file'); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); } // Outputs coverage when process.kill(process.pid, "SIGINT"); exits process. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/sigint') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (!common.isWindows) { if (output.signal !== 'SIGINT') { console.log(output.stderr.toString()); } assert.strictEqual(output.signal, 'SIGINT'); } assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('sigint.js', coverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); } // Outputs coverage from subprocess. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/spawn-subprocess') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('subprocess.js', coverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[1].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[1].ranges[1].count, 0); } // Outputs coverage from worker. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/worker') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('subprocess.js', coverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[1].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[1].ranges[1].count, 0); } // Does not output coverage if NODE_V8_COVERAGE is empty. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/spawn-subprocess-no-cov') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('subprocess.js', coverageDirectory); assert.strictEqual(fixtureCoverage, undefined); } // Disables async hooks before writing coverage. { const coverageDirectory = path.join(tmpdir.path, nextdir()); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/async-hooks') ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('async-hooks.js', coverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); } // Outputs coverage when the coverage directory is not absolute. { const coverageDirectory = nextdir(); const absoluteCoverageDirectory = path.join(tmpdir.path, coverageDirectory); const output = spawnSync(process.execPath, [ require.resolve('../fixtures/v8-coverage/basic') ], { cwd: tmpdir.path, env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); if (output.status !== 0) { console.log(output.stderr.toString()); } assert.strictEqual(output.status, 0); assert.strictEqual(output.stderr.toString(), ''); const fixtureCoverage = getFixtureCoverage('basic.js', absoluteCoverageDirectory); assert.ok(fixtureCoverage); // First branch executed. assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); // Second branch did not execute. assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); } // Extracts the coverage object for a given fixture name. function getFixtureCoverage(fixtureFile, coverageDirectory) { const coverageFiles = fs.readdirSync(coverageDirectory); for (const coverageFile of coverageFiles) { const coverage = require(path.join(coverageDirectory, coverageFile)); for (const fixtureCoverage of coverage.result) { if (fixtureCoverage.url.indexOf(`/${fixtureFile}`) !== -1) { return fixtureCoverage; } } } }