cmd/{go,cover}: fix for -coverprofile path capture with local pkg

When coverage testing a local package (defined by a relative import
path such as "./foo/bar") the convention when "-coverprofile" is used
has been to capture source files by full pathname, as opposed to
recording the full import path or the invented import path
("command-line-arguments/") created by the go command in the case of
building named Go files. Doing this makes it much easier to use
collected profiles with "go tool -cover -html=<profile>".

The support for this feature/convention wound up being inadvertantly
dropped during the GOEXPERIMENT=coverageredesign implementation; this
patch restores it.

Fixes #56433.

Change-Id: Ib9556fdc86011b00c155caa614ab23e5148f3eb4
Reviewed-on: https://go-review.googlesource.com/c/go/+/445917
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Than McIntosh 2022-10-26 11:33:28 -04:00
parent a3559f3301
commit 2730170f63
4 changed files with 59 additions and 1 deletions

View File

@ -74,7 +74,7 @@ var (
var pkgconfig coverage.CoverPkgConfig
var outputfiles []string // set whe -pkgcfg is in use
var outputfiles []string // set when -pkgcfg is in use
var profile string // The profile to read; the value of -html or -func
@ -484,6 +484,16 @@ func (f *File) postFunc(fn ast.Node, funcname string, flit bool, body *ast.Block
ppath := pkgconfig.PkgPath
filename := ppath + "/" + filepath.Base(fnpos.Filename)
// The convention for cmd/cover is that if the go command that
// kicks off coverage specifies a local import path (e.g. "go test
// -cover ./thispackage"), the tool will capture full pathnames
// for source files instead of relative paths, which tend to work
// more smoothly for "go tool cover -html". See also issue #56433
// for more details.
if pkgconfig.Local {
filename = f.name
}
// Hand off function to meta-data builder.
fd := coverage.FuncDesc{
Funcname: funcname,

View File

@ -1978,6 +1978,7 @@ func (b *Builder) writeCoverPkgInputs(a *Action, pconfigfile string, covoutputsf
// depending on user demand.
Granularity: "perblock",
OutConfig: p.Internal.CoverageCfg,
Local: p.Internal.Local,
}
if a.Package.Module != nil {
pcfg.ModulePath = a.Package.Module.Path

View File

@ -0,0 +1,40 @@
[short] skip
# collect coverage profile in text format
go test -coverprofile=blah.prof prog.go prog_test.go
# should not contain cmd-line pseudo-import-path
grep prog.go blah.prof
grep $PWD blah.prof
! grep command-line-arguments blah.prof
-- prog.go --
package main
func Mumble(x int) int {
if x < 0 {
return -x
}
return 42
}
func Grumble(y int) int {
return -y
}
func main() {
}
-- prog_test.go --
package main
import (
"testing"
)
func TestMumble(t *testing.T) {
if x := Mumble(10); x != 42 {
t.Errorf("Mumble(%d): got %d want %d", 10, x, 42)
}
}

View File

@ -25,6 +25,13 @@ type CoverPkgConfig struct {
// Module path for this package (empty if no go.mod in use)
ModulePath string
// Local mode indicates we're doing a coverage build or test of a
// package selected via local import path, e.g. "./..." or
// "./foo/bar" as opposed to a non-relative import path. See the
// corresponding field in cmd/go's PackageInternal struct for more
// info.
Local bool
}
// CoverFixupConfig contains annotations/notes generated by the