1'use strict'; 2 3if (!process.features.inspector) return; 4 5const common = require('../common'); 6const assert = require('assert'); 7const fs = require('fs'); 8const path = require('path'); 9const { spawnSync } = require('child_process'); 10 11const tmpdir = require('../common/tmpdir'); 12tmpdir.refresh(); 13 14let dirc = 0; 15function nextdir() { 16 return `cov_${++dirc}`; 17} 18 19// Outputs coverage when event loop is drained, with no async logic. 20{ 21 const coverageDirectory = path.join(tmpdir.path, nextdir()); 22 const output = spawnSync(process.execPath, [ 23 require.resolve('../fixtures/v8-coverage/basic'), 24 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 25 if (output.status !== 0) { 26 console.log(output.stderr.toString()); 27 } 28 assert.strictEqual(output.status, 0); 29 assert.strictEqual(output.stderr.toString(), ''); 30 const fixtureCoverage = getFixtureCoverage('basic.js', coverageDirectory); 31 assert.ok(fixtureCoverage); 32 // First branch executed. 33 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 34 // Second branch did not execute. 35 assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); 36} 37 38// Outputs coverage when error is thrown in first tick. 39{ 40 const coverageDirectory = path.join(tmpdir.path, nextdir()); 41 const output = spawnSync(process.execPath, [ 42 require.resolve('../fixtures/v8-coverage/throw'), 43 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 44 if (output.status !== 1) { 45 console.log(output.stderr.toString()); 46 } 47 assert.strictEqual(output.status, 1); 48 const fixtureCoverage = getFixtureCoverage('throw.js', coverageDirectory); 49 assert.ok(fixtureCoverage, 'coverage not found for file'); 50 // First branch executed. 51 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 52 // Second branch did not execute. 53 assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); 54} 55 56// Outputs coverage when process.exit(1) exits process. 57{ 58 const coverageDirectory = path.join(tmpdir.path, nextdir()); 59 const output = spawnSync(process.execPath, [ 60 require.resolve('../fixtures/v8-coverage/exit-1'), 61 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 62 if (output.status !== 1) { 63 console.log(output.stderr.toString()); 64 } 65 assert.strictEqual(output.status, 1); 66 assert.strictEqual(output.stderr.toString(), ''); 67 const fixtureCoverage = getFixtureCoverage('exit-1.js', coverageDirectory); 68 assert.ok(fixtureCoverage, 'coverage not found for file'); 69 // First branch executed. 70 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 71 // Second branch did not execute. 72 assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); 73} 74 75// Outputs coverage when process.kill(process.pid, "SIGINT"); exits process. 76{ 77 const coverageDirectory = path.join(tmpdir.path, nextdir()); 78 const output = spawnSync(process.execPath, [ 79 require.resolve('../fixtures/v8-coverage/sigint'), 80 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 81 if (!common.isWindows) { 82 if (output.signal !== 'SIGINT') { 83 console.log(output.stderr.toString()); 84 } 85 assert.strictEqual(output.signal, 'SIGINT'); 86 } 87 assert.strictEqual(output.stderr.toString(), ''); 88 const fixtureCoverage = getFixtureCoverage('sigint.js', coverageDirectory); 89 assert.ok(fixtureCoverage); 90 // First branch executed. 91 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 92 // Second branch did not execute. 93 assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); 94} 95 96// Outputs coverage from subprocess. 97{ 98 const coverageDirectory = path.join(tmpdir.path, nextdir()); 99 const output = spawnSync(process.execPath, [ 100 require.resolve('../fixtures/v8-coverage/spawn-subprocess'), 101 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 102 if (output.status !== 0) { 103 console.log(output.stderr.toString()); 104 } 105 assert.strictEqual(output.status, 0); 106 assert.strictEqual(output.stderr.toString(), ''); 107 const fixtureCoverage = getFixtureCoverage('subprocess.js', 108 coverageDirectory); 109 assert.ok(fixtureCoverage); 110 // First branch executed. 111 assert.strictEqual(fixtureCoverage.functions[1].ranges[0].count, 1); 112 // Second branch did not execute. 113 assert.strictEqual(fixtureCoverage.functions[1].ranges[1].count, 0); 114} 115 116// Outputs coverage from worker. 117{ 118 const coverageDirectory = path.join(tmpdir.path, nextdir()); 119 const output = spawnSync(process.execPath, [ 120 require.resolve('../fixtures/v8-coverage/worker'), 121 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 122 if (output.status !== 0) { 123 console.log(output.stderr.toString()); 124 } 125 assert.strictEqual(output.status, 0); 126 assert.strictEqual(output.stderr.toString(), ''); 127 const fixtureCoverage = getFixtureCoverage('subprocess.js', 128 coverageDirectory); 129 assert.ok(fixtureCoverage); 130 // First branch executed. 131 assert.strictEqual(fixtureCoverage.functions[1].ranges[0].count, 1); 132 // Second branch did not execute. 133 assert.strictEqual(fixtureCoverage.functions[1].ranges[1].count, 0); 134} 135 136// Does not output coverage if NODE_V8_COVERAGE is empty. 137{ 138 const coverageDirectory = path.join(tmpdir.path, nextdir()); 139 const output = spawnSync(process.execPath, [ 140 require.resolve('../fixtures/v8-coverage/spawn-subprocess-no-cov'), 141 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 142 if (output.status !== 0) { 143 console.log(output.stderr.toString()); 144 } 145 assert.strictEqual(output.status, 0); 146 assert.strictEqual(output.stderr.toString(), ''); 147 const fixtureCoverage = getFixtureCoverage('subprocess.js', 148 coverageDirectory); 149 assert.strictEqual(fixtureCoverage, undefined); 150} 151 152// Disables async hooks before writing coverage. 153{ 154 const coverageDirectory = path.join(tmpdir.path, nextdir()); 155 const output = spawnSync(process.execPath, [ 156 require.resolve('../fixtures/v8-coverage/async-hooks'), 157 ], { env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } }); 158 if (output.status !== 0) { 159 console.log(output.stderr.toString()); 160 } 161 assert.strictEqual(output.status, 0); 162 assert.strictEqual(output.stderr.toString(), ''); 163 const fixtureCoverage = getFixtureCoverage('async-hooks.js', 164 coverageDirectory); 165 assert.ok(fixtureCoverage); 166 // First branch executed. 167 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 168} 169 170// Outputs coverage when the coverage directory is not absolute. 171{ 172 const coverageDirectory = nextdir(); 173 const absoluteCoverageDirectory = path.join(tmpdir.path, coverageDirectory); 174 const output = spawnSync(process.execPath, [ 175 require.resolve('../fixtures/v8-coverage/basic'), 176 ], { 177 cwd: tmpdir.path, 178 env: { ...process.env, NODE_V8_COVERAGE: coverageDirectory } 179 }); 180 if (output.status !== 0) { 181 console.log(output.stderr.toString()); 182 } 183 assert.strictEqual(output.status, 0); 184 assert.strictEqual(output.stderr.toString(), ''); 185 const fixtureCoverage = getFixtureCoverage('basic.js', 186 absoluteCoverageDirectory); 187 assert.ok(fixtureCoverage); 188 // First branch executed. 189 assert.strictEqual(fixtureCoverage.functions[0].ranges[0].count, 1); 190 // Second branch did not execute. 191 assert.strictEqual(fixtureCoverage.functions[0].ranges[1].count, 0); 192} 193 194// Extracts the coverage object for a given fixture name. 195function getFixtureCoverage(fixtureFile, coverageDirectory) { 196 const coverageFiles = fs.readdirSync(coverageDirectory); 197 for (const coverageFile of coverageFiles) { 198 const coverage = require(path.join(coverageDirectory, coverageFile)); 199 for (const fixtureCoverage of coverage.result) { 200 if (fixtureCoverage.url.indexOf(`/${fixtureFile}`) !== -1) { 201 return fixtureCoverage; 202 } 203 } 204 } 205} 206