From 2730170f633811ca42aa4086aab6396c58449535 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 26 Oct 2022 11:33:28 -0400 Subject: [PATCH] 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=". 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 Run-TryBot: Than McIntosh TryBot-Result: Gopher Robot --- src/cmd/cover/cover.go | 12 +++++- src/cmd/go/internal/work/exec.go | 1 + .../script/cover_test_localpkg_filepath.txt | 40 +++++++++++++++++++ src/internal/coverage/cmddefs.go | 7 ++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 25574de773..53a5b6df41 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -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, diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index d0b5cbb53c..59eb373eae 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -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 diff --git a/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt b/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt new file mode 100644 index 0000000000..17c58081b2 --- /dev/null +++ b/src/cmd/go/testdata/script/cover_test_localpkg_filepath.txt @@ -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) + } +} diff --git a/src/internal/coverage/cmddefs.go b/src/internal/coverage/cmddefs.go index a146ca53e4..b30c37a08f 100644 --- a/src/internal/coverage/cmddefs.go +++ b/src/internal/coverage/cmddefs.go @@ -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 -- 2.50.0