cmd/go: fix percent covered problems with -coverpkg
This patch fixes some problems with how "go test -cover" was handling
tests involving A) multiple package tests and B) multiple packages
matched by "-coverpkg". In such scenarios the expectation is that the
percent statements covered metric for each package needs to be
relative to all statements in all packages matched by the -coverpkg
arg (this aspect of the reporting here was broken as part of
GOEXPERIMENT=coverageredesign).
The new scheme works as follows. If -coverpkg is in effect and is
matching multiple packages, and we have multiple test targets, then:
- each time a package is built for coverage, capture a meta-data
file fragment corresponding to just the meta-data for that package.
- create a new "writeCoverMeta" action, and interpose it between the
build actions for the covered packages and the run actions. The
"writeCoverMeta" action at runtime will emit a file
"metafiles.txt" containing a table mapping each covered package
(by import path) to its corresponding meta-data file fragment.
- pass in the "metafiles.txt" file to each run action, so that
when the test finishes running it will have an accurate picture
of _all_ covered packages, permitting it to calculate the correct
percentage.
Concrete example: suppose we have a top level directory with three
package subdirs, "a", "b", and "c", and from the top level, a user
runs "go test -coverpkg=./... ./...". This will result in (roughly)
the following action graph:
A note on init functions: prior to GOEXPERIMENT=coverageredesign
the "-coverpkg=..." flag was implemented by force-importing
all packages matched by "-coverpkg" into each instrumented package.
This meant that for the example above, when executing "a.test",
the init function for package "c" would fire even if package "a"
did not ordinarily import package "c". The new implementation
does not do this sort of forced importing, meaning that the coverage
percentages can be slightly different between 1.21 and 1.19 if
there are user-written init funcs.