diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 63fd13f7544db3..50fe23f7214ca2 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1899,12 +1899,21 @@ func (b *Builder) installHeader(ctx context.Context, a *Action) error { // regular outputs (instrumented source files) the cover tool also // writes a separate file (appearing first in the list of outputs) // that will contain coverage counters and meta-data. +// +// When an overlay is in use, it ensures the coverage tool processes the overlaid +// files rather than the original source files. func (b *Builder) cover(a *Action, infiles, outfiles []string, varName string, mode string) ([]string, error) { pkgcfg := a.Objdir + "pkgcfg.txt" covoutputs := a.Objdir + "coveroutfiles.txt" odir := filepath.Dir(outfiles[0]) cv := filepath.Join(odir, "covervars.go") outfiles = append([]string{cv}, outfiles...) + overlayInfiles := make([]string, 0, len(infiles)) + for _, f := range infiles { + overlayPath := fsys.Actual(f) + overlayInfiles = append(overlayInfiles, overlayPath) + } + if err := b.writeCoverPkgInputs(a, pkgcfg, covoutputs, outfiles); err != nil { return nil, err } @@ -1914,7 +1923,7 @@ func (b *Builder) cover(a *Action, infiles, outfiles []string, varName string, m "-var", varName, "-outfilelist", covoutputs, } - args = append(args, infiles...) + args = append(args, overlayInfiles...) if err := b.Shell(a).run(a.Objdir, "", nil, cfg.BuildToolexec, args); err != nil { return nil, err diff --git a/src/cmd/go/testdata/script/cover_overlay.txt b/src/cmd/go/testdata/script/cover_overlay.txt new file mode 100644 index 00000000000000..0440acf2aa50d1 --- /dev/null +++ b/src/cmd/go/testdata/script/cover_overlay.txt @@ -0,0 +1,77 @@ +# Test that coverage works correctly with overlays + +env GO111MODULE=on + +mkdir covmod +cd covmod + +-- go.mod -- +module example.com/covmod + +go 1.25 + +-- a.go -- +package a + +func Hello() string { + return "Hello: World" +} + +func Helper() string { + return "helper" +} + +-- a_test.go -- +package a + +import "testing" + +func TestHello(t *testing.T) { + got := Hello() + expected := "Hello: World" + if got != expected { + t.Fatalf("Hello() = %q, want %q", got, expected) + } +} + +func TestHelper(t *testing.T) { + got := Helper() + expected := "helper" + if got != expected { + t.Fatalf("Helper() = %q, want %q", got, expected) + } +} + +-- overlay/a.go -- +package a + +func Hello() string { + panic("overlay") +} + +func Helper() string { + panic("overlay helper") +} + +-- overlay.json -- +{"Replace": {"a.go": "overlay/a.go"}} + +exists overlay.json + +go mod tidy + +go test -v + +! exec sh -c '! go test -overlay=overlay.json -coverpkg=example.com/covmod 2>&1 | grep -q "panic: overlay"' + +! exec sh -c '! go test -overlay=overlay.json -run=TestHello -coverpkg=example.com/covmod 2>&1 | grep -q "panic: overlay"' + +! exec sh -c '! go test -overlay=overlay.json -run=TestHelper -coverpkg=example.com/covmod 2>&1 | grep -q "panic: overlay helper"' + +! go test -overlay=overlay.json -coverpkg=example.com/covmod -coverprofile=coverage.txt + +exists coverage.txt + +! grep -q 'overlay/a\.go' coverage.txt + +rm -f coverage.txt \ No newline at end of file