* Replace imports. * Migrate config.js to TS. * Replace build references. * Adjust TargetOS to infer from a runtime list. * Apply stricter rules for optional properties. * Restore options.outputDir to keep the PR without any logic change.
142 lines
4.7 KiB
JavaScript
142 lines
4.7 KiB
JavaScript
// Copyright (c) 2025 The Brave Authors. All rights reserved.
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
import { glob, rm } from 'node:fs/promises'
|
|
import fs from 'fs-extra'
|
|
import utils from '../lib/util.js'
|
|
import config from '../lib/config.ts'
|
|
|
|
const dedupe = (xs) => [...new Set(xs)]
|
|
const getTestBinariesFromRecordingsPath = (outputDir) => {
|
|
const regex = new RegExp(outputDir + '/coverage/(.*?)/')
|
|
return (recording) => {
|
|
const testName = recording.match(regex).at(1)
|
|
return `${outputDir}/${testName}`
|
|
}
|
|
}
|
|
|
|
export default (program) =>
|
|
program
|
|
.command('coverage_report')
|
|
.description(
|
|
[
|
|
'generates a coverage report.',
|
|
'Requires to build with --use_clang_coverage and run test.',
|
|
'HTML report will be in out/$BUILD_DIR/coverage/report/$NAME/dist',
|
|
].join('\n'),
|
|
)
|
|
.option('-C [build_dir]', 'build config (out/Debug, out/Release)')
|
|
.option('--target_arch [target_arch]', 'target architecture')
|
|
.option('--target_os <target_os>', 'target OS')
|
|
.option(
|
|
'--name [name]',
|
|
'name of the test report [defaults to coverage]',
|
|
'all',
|
|
)
|
|
.option(
|
|
'--clean',
|
|
'delete recordings and reports. Either all or those that match --tests [testSuites]',
|
|
)
|
|
.option(
|
|
'--tests [testSuites]',
|
|
'comma seperated list of testsuites to consider. By default it parses all recordings',
|
|
)
|
|
.arguments('[build_config]')
|
|
.action(async (buildConfig, args) => {
|
|
config.buildConfig = buildConfig || config.buildConfig
|
|
config.update(args)
|
|
const dirsGlob = args.tests ? `{${args.tests}}/**` : '**'
|
|
|
|
const out = `${config.outputDir}/coverage`
|
|
const reportPath = `${out}/report/${args.name}`
|
|
const profDataPath = `${reportPath}/coverage.profdata`
|
|
const distPath = `${reportPath}/dist`
|
|
|
|
const recordings = await Array.fromAsync(
|
|
glob(`${out}/${dirsGlob}/*.profraw`),
|
|
)
|
|
|
|
if (args.clean) {
|
|
await Promise.all(
|
|
recordings
|
|
.concat([reportPath])
|
|
.map((path) => rm(path, { recursive: true, force: true })),
|
|
)
|
|
|
|
return
|
|
}
|
|
|
|
const allTestSuites = dedupe(
|
|
recordings.map(getTestBinariesFromRecordingsPath(config.outputDir)),
|
|
)
|
|
|
|
// llvm-cov needs a .profdata (llvms .lcov equivalent) and
|
|
// binaries that include the symbols that are instrumented to generate a report
|
|
// Weirdly it appears that the json export is unaffected.
|
|
// We probably want to use gcov / genhtml instead of llvm-cov
|
|
// For now - if we can - only use brave_browser_tests binary
|
|
// since it will have the most amount of symbols to generate the report.
|
|
// It will still include coverage information of code paths of other test suites
|
|
// as long as their symbols are present in the brave_browser_test binary
|
|
const hasBBT = allTestSuites.find((x) =>
|
|
x.includes('brave_browser_tests'),
|
|
)
|
|
const testSuites = hasBBT
|
|
? [`${config.outputDir}/brave_browser_tests`]
|
|
: allTestSuites
|
|
|
|
if (!recordings.length) {
|
|
console.log(
|
|
`glob ${out}/${dirsGlob}/*.profraw didn't yield any recordings!\n make sure you've built with --use_coverage and ran the appropriate tests`,
|
|
)
|
|
return
|
|
}
|
|
|
|
const cwd = config.outputDir
|
|
const coverageToolPath = `${config.srcDir}/third_party/llvm-build/Release+Asserts/bin`
|
|
// fetch coverage tools if not available
|
|
await fs.mkdirp(distPath)
|
|
|
|
await utils.runAsync(
|
|
`${coverageToolPath}/llvm-profdata`,
|
|
['merge', '-sparse', '-o', profDataPath, ...recordings],
|
|
{ cwd },
|
|
)
|
|
|
|
await utils.runAsync(
|
|
`${coverageToolPath}/llvm-cov`,
|
|
[
|
|
'show',
|
|
`-compilation-dir=${config.outputDir}`,
|
|
`-instr-profile=${profDataPath}`,
|
|
'-format=html',
|
|
`-output-dir=${distPath}`,
|
|
...testSuites,
|
|
],
|
|
{ cwd },
|
|
)
|
|
|
|
const output = await utils.runAsync(
|
|
`${coverageToolPath}/llvm-cov`,
|
|
[
|
|
'export',
|
|
`-compilation-dir=${config.outputDir}`,
|
|
`-instr-profile=${profDataPath}`,
|
|
'--summary-only',
|
|
...testSuites,
|
|
],
|
|
{ cwd, stdio: 'pipe' },
|
|
)
|
|
|
|
try {
|
|
const summary = JSON.parse(output)
|
|
await fs.writeJSON(`${distPath}/coverage.json`, summary)
|
|
console.log(summary.data[0].totals)
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
|
|
console.log(`\ncoverage reports written to ${out}/report`)
|
|
})
|