11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('node:assert');
41cb0ef41Sopenharmony_ciconst { spawnSync } = require('node:child_process');
51cb0ef41Sopenharmony_ciconst { readdirSync } = require('node:fs');
61cb0ef41Sopenharmony_ciconst { test } = require('node:test');
71cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
81cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir');
91cb0ef41Sopenharmony_ciconst skipIfNoInspector = {
101cb0ef41Sopenharmony_ci  skip: !process.features.inspector ? 'inspector disabled' : false
111cb0ef41Sopenharmony_ci};
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_citmpdir.refresh();
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cifunction findCoverageFileForPid(pid) {
161cb0ef41Sopenharmony_ci  const pattern = `^coverage\\-${pid}\\-(\\d{13})\\-(\\d+)\\.json$`;
171cb0ef41Sopenharmony_ci  const regex = new RegExp(pattern);
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ci  return readdirSync(tmpdir.path).find((file) => {
201cb0ef41Sopenharmony_ci    return regex.test(file);
211cb0ef41Sopenharmony_ci  });
221cb0ef41Sopenharmony_ci}
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cifunction getTapCoverageFixtureReport() {
251cb0ef41Sopenharmony_ci  const report = [
261cb0ef41Sopenharmony_ci    '# start of coverage report',
271cb0ef41Sopenharmony_ci    '# file | line % | branch % | funcs % | uncovered lines',
281cb0ef41Sopenharmony_ci    '# test/fixtures/test-runner/coverage.js | 78.65 | 38.46 | 60.00 | 12, ' +
291cb0ef41Sopenharmony_ci    '13, 16, 17, 18, 19, 20, 21, 22, 27, 39, 43, 44, 61, 62, 66, 67, 71, 72',
301cb0ef41Sopenharmony_ci    '# test/fixtures/test-runner/invalid-tap.js | 100.00 | 100.00 | 100.00 | ',
311cb0ef41Sopenharmony_ci    '# test/fixtures/v8-coverage/throw.js | 71.43 | 50.00 | 100.00 | 5, 6',
321cb0ef41Sopenharmony_ci    '# all files | 78.35 | 43.75 | 60.00 |',
331cb0ef41Sopenharmony_ci    '# end of coverage report',
341cb0ef41Sopenharmony_ci  ].join('\n');
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  if (common.isWindows) {
371cb0ef41Sopenharmony_ci    return report.replaceAll('/', '\\');
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  return report;
411cb0ef41Sopenharmony_ci}
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_cifunction getSpecCoverageFixtureReport() {
441cb0ef41Sopenharmony_ci  /* eslint-disable max-len */
451cb0ef41Sopenharmony_ci  const report = [
461cb0ef41Sopenharmony_ci    '\u2139 start of coverage report',
471cb0ef41Sopenharmony_ci    '\u2139 -------------------------------------------------------------------------------------------------------------------',
481cb0ef41Sopenharmony_ci    '\u2139 file                                     | line % | branch % | funcs % | uncovered lines',
491cb0ef41Sopenharmony_ci    '\u2139 -------------------------------------------------------------------------------------------------------------------',
501cb0ef41Sopenharmony_ci    '\u2139 test/fixtures/test-runner/coverage.js    |  78.65 |    38.46 |   60.00 | 12-13 16-22 27 39 43-44 61-62 66-67 71-72',
511cb0ef41Sopenharmony_ci    '\u2139 test/fixtures/test-runner/invalid-tap.js | 100.00 |   100.00 |  100.00 | ',
521cb0ef41Sopenharmony_ci    '\u2139 test/fixtures/v8-coverage/throw.js       |  71.43 |    50.00 |  100.00 | 5-6',
531cb0ef41Sopenharmony_ci    '\u2139 -------------------------------------------------------------------------------------------------------------------',
541cb0ef41Sopenharmony_ci    '\u2139 all files                                |  78.35 |    43.75 |   60.00 |',
551cb0ef41Sopenharmony_ci    '\u2139 -------------------------------------------------------------------------------------------------------------------',
561cb0ef41Sopenharmony_ci    '\u2139 end of coverage report',
571cb0ef41Sopenharmony_ci  ].join('\n');
581cb0ef41Sopenharmony_ci  /* eslint-enable max-len */
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  if (common.isWindows) {
611cb0ef41Sopenharmony_ci    return report.replaceAll('/', '\\');
621cb0ef41Sopenharmony_ci  }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  return report;
651cb0ef41Sopenharmony_ci}
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_citest('test coverage report', async (t) => {
681cb0ef41Sopenharmony_ci  await t.test('handles the inspector not being available', (t) => {
691cb0ef41Sopenharmony_ci    if (process.features.inspector) {
701cb0ef41Sopenharmony_ci      return;
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci    const fixture = fixtures.path('test-runner', 'coverage.js');
741cb0ef41Sopenharmony_ci    const args = ['--experimental-test-coverage', fixture];
751cb0ef41Sopenharmony_ci    const result = spawnSync(process.execPath, args);
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci    assert(!result.stdout.toString().includes('# start of coverage report'));
781cb0ef41Sopenharmony_ci    assert(result.stderr.toString().includes('coverage could not be collected'));
791cb0ef41Sopenharmony_ci    assert.strictEqual(result.status, 0);
801cb0ef41Sopenharmony_ci    assert(!findCoverageFileForPid(result.pid));
811cb0ef41Sopenharmony_ci  });
821cb0ef41Sopenharmony_ci});
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_citest('test tap coverage reporter', skipIfNoInspector, async (t) => {
851cb0ef41Sopenharmony_ci  await t.test('coverage is reported and dumped to NODE_V8_COVERAGE if present', (t) => {
861cb0ef41Sopenharmony_ci    const fixture = fixtures.path('test-runner', 'coverage.js');
871cb0ef41Sopenharmony_ci    const args = ['--experimental-test-coverage', '--test-reporter', 'tap', fixture];
881cb0ef41Sopenharmony_ci    const options = { env: { ...process.env, NODE_V8_COVERAGE: tmpdir.path } };
891cb0ef41Sopenharmony_ci    const result = spawnSync(process.execPath, args, options);
901cb0ef41Sopenharmony_ci    const report = getTapCoverageFixtureReport();
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    assert(result.stdout.toString().includes(report));
931cb0ef41Sopenharmony_ci    assert.strictEqual(result.stderr.toString(), '');
941cb0ef41Sopenharmony_ci    assert.strictEqual(result.status, 0);
951cb0ef41Sopenharmony_ci    assert(findCoverageFileForPid(result.pid));
961cb0ef41Sopenharmony_ci  });
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  await t.test('coverage is reported without NODE_V8_COVERAGE present', (t) => {
991cb0ef41Sopenharmony_ci    const fixture = fixtures.path('test-runner', 'coverage.js');
1001cb0ef41Sopenharmony_ci    const args = ['--experimental-test-coverage', '--test-reporter', 'tap', fixture];
1011cb0ef41Sopenharmony_ci    const result = spawnSync(process.execPath, args);
1021cb0ef41Sopenharmony_ci    const report = getTapCoverageFixtureReport();
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci    assert(result.stdout.toString().includes(report));
1051cb0ef41Sopenharmony_ci    assert.strictEqual(result.stderr.toString(), '');
1061cb0ef41Sopenharmony_ci    assert.strictEqual(result.status, 0);
1071cb0ef41Sopenharmony_ci    assert(!findCoverageFileForPid(result.pid));
1081cb0ef41Sopenharmony_ci  });
1091cb0ef41Sopenharmony_ci});
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_citest('test spec coverage reporter', skipIfNoInspector, async (t) => {
1121cb0ef41Sopenharmony_ci  await t.test('coverage is reported and dumped to NODE_V8_COVERAGE if present', (t) => {
1131cb0ef41Sopenharmony_ci    const fixture = fixtures.path('test-runner', 'coverage.js');
1141cb0ef41Sopenharmony_ci    const args = ['--experimental-test-coverage', '--test-reporter', 'spec', fixture];
1151cb0ef41Sopenharmony_ci    const options = { env: { ...process.env, NODE_V8_COVERAGE: tmpdir.path } };
1161cb0ef41Sopenharmony_ci    const result = spawnSync(process.execPath, args, options);
1171cb0ef41Sopenharmony_ci    const report = getSpecCoverageFixtureReport();
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    assert(result.stdout.toString().includes(report));
1201cb0ef41Sopenharmony_ci    assert.strictEqual(result.stderr.toString(), '');
1211cb0ef41Sopenharmony_ci    assert.strictEqual(result.status, 0);
1221cb0ef41Sopenharmony_ci    assert(findCoverageFileForPid(result.pid));
1231cb0ef41Sopenharmony_ci  });
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  await t.test('coverage is reported without NODE_V8_COVERAGE present', (t) => {
1261cb0ef41Sopenharmony_ci    const fixture = fixtures.path('test-runner', 'coverage.js');
1271cb0ef41Sopenharmony_ci    const args = ['--experimental-test-coverage', '--test-reporter', 'spec', fixture];
1281cb0ef41Sopenharmony_ci    const result = spawnSync(process.execPath, args);
1291cb0ef41Sopenharmony_ci    const report = getSpecCoverageFixtureReport();
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci    assert(result.stdout.toString().includes(report));
1321cb0ef41Sopenharmony_ci    assert.strictEqual(result.stderr.toString(), '');
1331cb0ef41Sopenharmony_ci    assert.strictEqual(result.status, 0);
1341cb0ef41Sopenharmony_ci    assert(!findCoverageFileForPid(result.pid));
1351cb0ef41Sopenharmony_ci  });
1361cb0ef41Sopenharmony_ci});
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_citest('single process coverage is the same with --test', skipIfNoInspector, () => {
1391cb0ef41Sopenharmony_ci  const fixture = fixtures.path('test-runner', 'coverage.js');
1401cb0ef41Sopenharmony_ci  const args = [
1411cb0ef41Sopenharmony_ci    '--test', '--experimental-test-coverage', '--test-reporter', 'tap', fixture,
1421cb0ef41Sopenharmony_ci  ];
1431cb0ef41Sopenharmony_ci  const result = spawnSync(process.execPath, args);
1441cb0ef41Sopenharmony_ci  const report = getTapCoverageFixtureReport();
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  assert.strictEqual(result.stderr.toString(), '');
1471cb0ef41Sopenharmony_ci  assert(result.stdout.toString().includes(report));
1481cb0ef41Sopenharmony_ci  assert.strictEqual(result.status, 0);
1491cb0ef41Sopenharmony_ci  assert(!findCoverageFileForPid(result.pid));
1501cb0ef41Sopenharmony_ci});
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_citest('coverage is combined for multiple processes', skipIfNoInspector, () => {
1531cb0ef41Sopenharmony_ci  let report = [
1541cb0ef41Sopenharmony_ci    '# start of coverage report',
1551cb0ef41Sopenharmony_ci    '# file | line % | branch % | funcs % | uncovered lines',
1561cb0ef41Sopenharmony_ci    '# test/fixtures/v8-coverage/combined_coverage/common.js | 89.86 | ' +
1571cb0ef41Sopenharmony_ci    '62.50 | 100.00 | 8, 13, 14, 18, 34, 35, 53',
1581cb0ef41Sopenharmony_ci    '# test/fixtures/v8-coverage/combined_coverage/first.test.js | 83.33 | ' +
1591cb0ef41Sopenharmony_ci    '100.00 | 50.00 | 5, 6',
1601cb0ef41Sopenharmony_ci    '# test/fixtures/v8-coverage/combined_coverage/second.test.js | 100.00 ' +
1611cb0ef41Sopenharmony_ci    '| 100.00 | 100.00 | ',
1621cb0ef41Sopenharmony_ci    '# test/fixtures/v8-coverage/combined_coverage/third.test.js | 100.00 | ' +
1631cb0ef41Sopenharmony_ci    '100.00 | 100.00 | ',
1641cb0ef41Sopenharmony_ci    '# all files | 92.11 | 72.73 | 88.89 |',
1651cb0ef41Sopenharmony_ci    '# end of coverage report',
1661cb0ef41Sopenharmony_ci  ].join('\n');
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ci  if (common.isWindows) {
1691cb0ef41Sopenharmony_ci    report = report.replaceAll('/', '\\');
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci  const fixture = fixtures.path('v8-coverage', 'combined_coverage');
1731cb0ef41Sopenharmony_ci  const args = [
1741cb0ef41Sopenharmony_ci    '--test', '--experimental-test-coverage', '--test-reporter', 'tap', fixture,
1751cb0ef41Sopenharmony_ci  ];
1761cb0ef41Sopenharmony_ci  const result = spawnSync(process.execPath, args, {
1771cb0ef41Sopenharmony_ci    env: { ...process.env, NODE_TEST_TMPDIR: tmpdir.path }
1781cb0ef41Sopenharmony_ci  });
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci  assert.strictEqual(result.stderr.toString(), '');
1811cb0ef41Sopenharmony_ci  assert(result.stdout.toString().includes(report));
1821cb0ef41Sopenharmony_ci  assert.strictEqual(result.status, 0);
1831cb0ef41Sopenharmony_ci});
184