cmd/cover: use -toolexec in tests to run newly built cover program

This ensures that "go test cmd/cover" tests the current cover program,
not the installed cover program.

Change-Id: I58e718ded7eb1cd8da448d0194262209bb025b20
Reviewed-on: https://go-review.googlesource.com/c/153058
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Ian Lance Taylor 2018-12-06 14:08:19 -08:00
parent d063b7c6d3
commit 77caea5bf2
2 changed files with 80 additions and 11 deletions

View file

@ -30,9 +30,10 @@ const (
var (
// Input files.
testMain = filepath.Join(testdata, "main.go")
testTest = filepath.Join(testdata, "test.go")
coverProfile = filepath.Join(testdata, "profile.cov")
testMain = filepath.Join(testdata, "main.go")
testTest = filepath.Join(testdata, "test.go")
coverProfile = filepath.Join(testdata, "profile.cov")
toolexecSource = filepath.Join(testdata, "toolexec.go")
// The HTML test files are in a separate directory
// so they are a complete package.
@ -53,11 +54,17 @@ var (
// testcover is a newly built version of the cover program.
testcover string
// testcoverErr records an error building testcover.
// toolexec is a program to use as the go tool's -toolexec argument.
toolexec string
// testcoverErr records an error building testcover or toolexec.
testcoverErr error
// testcoverOnce is used to build testcover once.
testcoverOnce sync.Once
// toolexecArg is the argument to pass to the go tool.
toolexecArg string
)
var debug = flag.Bool("debug", false, "keep rewritten files for debugging")
@ -94,14 +101,43 @@ func buildCover(t *testing.T) {
t.Helper()
testenv.MustHaveGoBuild(t)
testcoverOnce.Do(func() {
testcover = filepath.Join(testTempDir, "testcover.exe")
t.Logf("running [go build -o %s]", testcover)
out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover).CombinedOutput()
t.Logf("%s", out)
testcoverErr = err
var wg sync.WaitGroup
wg.Add(2)
var err1, err2 error
go func() {
defer wg.Done()
testcover = filepath.Join(testTempDir, "cover.exe")
t.Logf("running [go build -o %s]", testcover)
out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover).CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
err1 = err
}()
go func() {
defer wg.Done()
toolexec = filepath.Join(testTempDir, "toolexec.exe")
t.Logf("running [go -build -o %s %s]", toolexec, toolexecSource)
out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", toolexec, toolexecSource).CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
err2 = err
}()
wg.Wait()
testcoverErr = err1
if err2 != nil && err1 == nil {
testcoverErr = err2
}
toolexecArg = "-toolexec=" + toolexec + " " + testcover
})
if testcoverErr != nil {
t.Fatal("failed to build testcover program:", testcoverErr)
t.Fatal("failed to build testcover or toolexec program:", testcoverErr)
}
}
@ -335,7 +371,7 @@ func TestCoverHTML(t *testing.T) {
buildCover(t)
// go test -coverprofile testdata/html/html.cov cmd/cover/testdata/html
cmd := exec.Command(testenv.GoToolPath(t), "test", "-coverprofile", htmlProfile, "cmd/cover/testdata/html")
cmd := exec.Command(testenv.GoToolPath(t), "test", toolexecArg, "-coverprofile", htmlProfile, "cmd/cover/testdata/html")
run(cmd, t)
// testcover -html testdata/html/html.cov -o testdata/html/html.html
cmd = exec.Command(testcover, "-html", htmlProfile, "-o", htmlHTML)

33
src/cmd/cover/testdata/toolexec.go vendored Normal file
View file

@ -0,0 +1,33 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The toolexec program is a helper program for cmd/cover tests.
// It is used so that the go tool will call the newly built version
// of the cover program, rather than the installed one.
//
// The tests arrange to run the go tool with the argument
// -toolexec="/path/to/toolexec /path/to/testcover"
// The go tool will invoke this program (compiled into /path/to/toolexec)
// with the arguments shown above followed by the command to run.
// This program will check whether it is expected to run the cover
// program, and if so replace it with /path/to/testcover.
package main
import (
"os"
"os/exec"
"strings"
)
func main() {
if strings.HasSuffix(strings.TrimSuffix(os.Args[2], ".exe"), "cover") {
os.Args[2] = os.Args[1]
}
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
os.Exit(1)
}
}