Help us shape the future of Go! Take the 2026 Go Developer Survey

covblocks

command
v0.69.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: BSD-3-Clause Imports: 8 Imported by: 0

Documentation

Overview

Command covblocks counts the BLOCKS a Go coverage profile never entered, and fails when there are any.

It exists because the obvious instrument gives the wrong answer and the convenient one is a one-liner nobody tests.

⛔ `go tool cover -func` ROUNDS TO ONE DECIMAL. So a gate written as

go tool cover -func=cov.out | tail -1 | grep -q '100.0%'

passes at 99.95%, and that is not a corner case anybody has to wait for. Demonstrated 2026-10-11 on a real go-pkgx/bk profile — 2592 blocks, 4221 statements, nothing uncovered — with exactly ONE one-statement block flipped to zero:

$ go tool cover -func=one-off.out | tail -1
total:                  (statements)            100.0%      → exit 0
$ covblocks one-off.out
…/advisories.go:34.3,35.1 1 stmt(s)
2592 block(s), 4221 statement(s); 1 block(s) uncovered, 1 statement(s) uncovered
covblocks: 1 uncovered block(s) > 0 allowed                 → exit 1

One statement in 4221 is 0.024%, so `-func` prints a clean hundred. The threshold is arithmetic, not luck: any profile with fewer than one uncovered statement per two thousand reads as 100.0%.

A note on where this came from, because the remembered version was wrong. A note in this fleet said `-func` had printed 100.0% for a profile with THREE uncovered blocks. Re-measured, that profile (3949 statements, 4 uncovered) prints 99.9% — so `-func` WOULD have caught that one, and the note's number did not survive being checked. The hazard is real and the example above is constructed to show it rather than recalled.

`-func` has a second limitation found the same day: it resolves source files through the module, so reading a profile from outside its checkout fails with "no required module provides package …". A block count needs only the profile.

⛔ AND THE ONE-LINER IS NOT THE FORMAT. The idiom it replaces is

awk 'NR>1 && $NF==0' cov.out

which reads one line at a time. The profile format permits the SAME block to appear more than once, and Go's own parser sums the counts — golang.org/x/tools/cover/profile.go does `p.Blocks[j-1].Count += b.Count`, and errors if two entries for one position disagree about NumStmt. A line-by-line check would call a block uncovered on the strength of one entry while another entry covered it.

Measured honestly: of three real profiles from this fleet (2592, 1268 and 2592 blocks), NONE repeated a block, so that is a difference in SEMANTICS and not a bug anybody is hitting today. This tool parses with x/tools/cover so it is right by construction rather than by luck — and because a second implementation of a format is the thing that drifts.

covblocks cov.out                 # the uncovered blocks, and the totals
covblocks --max 3 cov.out         # tolerate three, fail on a fourth
covblocks a.out b.out             # several profiles, one verdict

⛔ AN EMPTY PROFILE IS A FAILURE. A profile with no blocks reports the same "0 uncovered" as one that covered everything, and this fleet has published a zero that meant "could not read".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL