~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

The coverage gate names the lines it counts as missed, and no others

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:harness/cov-missed-lines
harness/cov.mjs+41−36
@@ -495,11 +495,13 @@ const gate = () => {
return r.status ?? 1
}
/// Says each line no run reached, by file and by the function it is in.
/// The table adds up each function's lines, each generic taken at its
/// best instance, so a line one function misses counts though another
/// reaches it, and the merged views (lcov, text) show it reached: the
/// lines are read here as the table counts them, function by function.
/// Says each line the gate counts as missed, by file and by the function
/// it is in. The table counts a function's lines once for all its
/// instances, a generic's or a macro's, at the instance that reaches the
/// most of them, and counts a line again for each function it is in: the
/// lines are read here the same way, so the list is the table's misses
/// and no more, though another instance of a generic reaches a line its
/// best one does not.
const missed = (short) => {
const json = join(report, 'missed.json')
spawnSync(
@@ -508,40 +510,43 @@ const missed = (short) => {
{ cwd: root, env: { ...env, CARGO_LLVM_COV_TARGET_DIR: report, CARGO_LLVM_COV_BUILD_DIR: report }, stdio: 'inherit' },
)
if (!existsSync(json)) return
const seen = new Set()
console.log('Uncovered:')
const functions = JSON.parse(readFileSync(json, 'utf8')).data[0].functions
// Where each function some run called starts, to tell one never called
// from another instance of it that was.
const starts = (f) => f.filenames.map((file, i) => [relative(root, file), f.regions.find((r) => r[5] === i)])
const called = new Set(functions.filter((f) => f.count).flatMap((f) => starts(f).filter(([, r]) => r).map(([at, r]) => `${at}:${r[0]}`)))
for (const f of functions) {
if (!f.count) {
// A function no run called, a closure most often: where it starts.
for (const [at, first] of starts(f)) {
const key = first && `${at}:${first[0]}`
if (!key || called.has(key) || seen.has(key) || !short.some((s) => at.endsWith(s))) continue
seen.add(key)
console.log(` ${key} in ${f.name}, never called`)
}
// A region: line and column it starts and ends at, its count, its
// file, the file it expands, and its kind, 0 being code.
const at = (f) => relative(root, f.filenames[0])
const first = (f) => f.regions.find((r) => r[5] === 0)
// The lines an instance misses: where each code region starts that no
// reached region in the same file covers. A macro's call is an
// expansion region, and one reached reaches its line.
const misses = (f) => {
const here = f.regions.filter((r) => r[5] === 0)
const lines = here.filter((r) => r[7] === 0).map((r) => r[0])
return [...new Set(lines.filter((l) => !here.some((r) => r[4] > 0 && r[0] <= l && l <= r[2])))]
}
// The instances of one function start at the same place.
const groups = new Map()
for (const f of JSON.parse(readFileSync(json, 'utf8')).data[0].functions) {
const start = first(f)
if (!start || !short.some((s) => at(f).endsWith(s))) continue
const key = `${at(f)}:${start[0]}:${start[1]}`
groups.set(key, [...(groups.get(key) ?? []), f])
}
const out = []
for (const fs of groups.values()) {
const f = fs[0]
if (!fs.some((f) => f.count)) {
out.push([at(f), first(f)[0], f.name, ', never called'])
continue
}
// A region: line and column it starts and ends at, its count, its
// file, the file it expands, and its kind, 0 being code.
for (const [i, file] of f.filenames.entries()) {
const at = relative(root, file)
if (!short.some((s) => at.endsWith(s))) continue
// A macro's call is an expansion region: one reached reaches its line.
const here = f.regions.filter((r) => r[5] === i)
for (const [start] of here.filter((r) => r[7] === 0)) {
if (here.some((r) => r[4] > 0 && r[0] <= start && start <= r[2])) continue
const key = `${at}:${start}`
if (seen.has(key)) continue
seen.add(key)
console.log(` ${key} in ${f.name}`)
}
}
const best = fs
.filter((f) => f.count)
.map((f) => ({ f, lines: misses(f) }))
.reduce((a, b) => (b.lines.length < a.lines.length ? b : a))
for (const l of best.lines) out.push([at(best.f), l, best.f.name, ''])
}
console.log('Uncovered:')
const rows = out.map(([file, line, name, never]) => [file, line, name + never])
rows.sort((a, b) => a[0].localeCompare(b[0]) || a[1] - b[1])
for (const [file, line, name] of rows) console.log(` ${file}:${line} in ${name}`)
}
let status = gate()