chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
The coverage gate names lines only a function's test build has and misses
harness/cov.mjs+28−6
| @@ -507,7 +507,9 @@ const gate = () => { | ||
/// 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. | ||
/// best one does not. Where instances differ in their lines, as when one | ||
/// is built only for a crate's own tests, the table's misses are those of | ||
/// the instance with the most lines, and those are named. | ||
const missed = (short) => { | ||
const json = join(report, 'missed.json') | ||
spawnSync( | ||
| @@ -528,6 +530,13 @@ const missed = (short) => { | ||
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 lines an instance has: every line a code region of it spans, as | ||
// llvm-cov counts a line inside a region though nothing starts on it. | ||
const mapped = (f) => { | ||
const lines = new Set() | ||
for (const r of f.regions.filter((r) => r[5] === 0 && r[7] !== 2)) for (let l = r[0]; l <= r[2]; l++) lines.add(l) | ||
return lines | ||
} | ||
// 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) { | ||
| @@ -543,11 +552,24 @@ const missed = (short) => { | ||
out.push([at(f), first(f)[0], f.name, ', never called']) | ||
continue | ||
} | ||
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, '']) | ||
const seen = fs.map((f) => { | ||
const miss = f.count ? misses(f) : [] | ||
const lines = mapped(f) | ||
return { f, miss, lines, covered: f.count ? lines.size - miss.length : 0 } | ||
}) | ||
const best = seen.filter((s) => s.f.count).reduce((a, b) => (b.miss.length < a.miss.length ? b : a)) | ||
for (const l of best.miss) out.push([at(best.f), l, best.f.name, '']) | ||
// The table takes the most lines any instance has, less the most any | ||
// reaches: an instance with lines the others lack, as one built only | ||
// for a crate's own tests (a `#[cfg(test)]` arm), counts the lines it | ||
// misses though another instance reaches them. Those are named too. | ||
const widest = seen.reduce((a, b) => (b.lines.size > a.lines.size ? b : a)) | ||
const counted = widest.lines.size - Math.max(...seen.map((s) => s.covered)) | ||
if (counted > best.miss.length) { | ||
const lacking = widest.f.count ? widest.miss : [...widest.lines] | ||
const extra = lacking.filter((l) => !best.miss.includes(l)) | ||
for (const l of extra) out.push([at(widest.f), l, widest.f.name, ', in the instance with the most lines']) | ||
} | ||
} | ||
console.log('Uncovered:') | ||
const rows = out.map(([file, line, name, never]) => [file, line, name + never]) | ||