aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/covdata/tool_test.go
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2022-05-18 18:48:56 -0400
committerThan McIntosh <thanm@google.com>2022-09-29 14:13:50 +0000
commitf2ee3414689add84c6e6d2d3f44dacde5129b18d (patch)
treeabe1be466d83d0c3ea1a7468d9f285ac09dd7d5b /src/cmd/covdata/tool_test.go
parent9d6dc32edd03f24a3ecacfcf4cdf54f561834c33 (diff)
downloadgo-f2ee3414689add84c6e6d2d3f44dacde5129b18d.tar.xz
cmd{cover,covdata,go}: better coverage for tests that build tools
Some of the unit tests in Go's "cmd" tree wind up building a separate copy of the tool being tested, then exercise the freshly built tool as a way of doing regression tests. The intent is to make sure that "go test" is testing the current state of the source code, as opposed to whatever happened to be current when "go install <tool>" was last run. Doing things this way is unfriendly for coverage testing. If I run "go test -cover cmd/mumble", and the cmd/mumble test harness builds a fresh copy of mumble.exe, any runs of that new executable won't generate coverage data. This patch updates the test harnesses to use the unit test executable as a stand-in for the tool itself, so that if "go test -cover" is in effect, we get the effect of building the tool executable for coverage as well. Doing this brings up the overall test coverage number for cmd/cover quite dramatically: before change: $ go test -cover . ok cmd/cover 1.100s coverage: 1.5% of statements after change: $ go test -cover . ok cmd/cover 1.299s coverage: 84.2% of statements Getting this to work requires a small change in the Go command as well, to set GOCOVERDIR prior to executing a test binary. Updates #51430. Change-Id: Ifcf0ea85773b80fcda794aae3702403ec8e0b733 Reviewed-on: https://go-review.googlesource.com/c/go/+/404299 Reviewed-by: Bryan Mills <bcmills@google.com>
Diffstat (limited to 'src/cmd/covdata/tool_test.go')
-rw-r--r--src/cmd/covdata/tool_test.go67
1 files changed, 62 insertions, 5 deletions
diff --git a/src/cmd/covdata/tool_test.go b/src/cmd/covdata/tool_test.go
index 6caf8fa10d..584ba71d46 100644
--- a/src/cmd/covdata/tool_test.go
+++ b/src/cmd/covdata/tool_test.go
@@ -5,20 +5,79 @@
package main_test
import (
+ cmdcovdata "cmd/covdata"
+ "flag"
"fmt"
"internal/coverage/pods"
"internal/goexperiment"
"internal/testenv"
"io/ioutil"
+ "log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strconv"
"strings"
+ "sync"
"testing"
)
+// Path to unit test executable to be used as standin for 'go tool covdata'
+var testcovdata string
+
+// Top level tempdir for test.
+var testTempDir string
+
+// If set, this will preserve all the tmpdir files from the test run.
+var preserveTmp = flag.Bool("preservetmp", false, "keep tmpdir files for debugging")
+
+// TestMain used here so that we can leverage the test executable
+// itself as a cmd/covdata executable; compare to similar usage in
+// the cmd/go tests.
+func TestMain(m *testing.M) {
+ // When CMDCOVDATA_TEST_RUN_MAIN is set, we're reusing the test
+ // binary as cmd/cover. In this case we run the main func exported
+ // via export_test.go, and exit; CMDCOVDATA_TEST_RUN_MAIN is set below
+ // for actual test invocations.
+ if os.Getenv("CMDCOVDATA_TEST_RUN_MAIN") != "" {
+ cmdcovdata.Main()
+ os.Exit(0)
+ }
+ flag.Parse()
+ topTmpdir, err := os.MkdirTemp("", "cmd-covdata-test-")
+ if err != nil {
+ log.Fatal(err)
+ }
+ testTempDir = topTmpdir
+ if !*preserveTmp {
+ defer os.RemoveAll(topTmpdir)
+ } else {
+ fmt.Fprintf(os.Stderr, "debug: preserving tmpdir %s\n", topTmpdir)
+ }
+ os.Setenv("CMDCOVDATA_TEST_RUN_MAIN", "true")
+ testExe, err := os.Executable()
+ if err != nil {
+ log.Fatal(err)
+ }
+ testcovdata = testExe
+ os.Exit(m.Run())
+}
+
+var tdmu sync.Mutex
+var tdcount int
+
+func tempDir(t *testing.T) string {
+ tdmu.Lock()
+ dir := filepath.Join(testTempDir, fmt.Sprintf("%03d", tdcount))
+ tdcount++
+ if err := os.Mkdir(dir, 0777); err != nil {
+ t.Fatal(err)
+ }
+ defer tdmu.Unlock()
+ return dir
+}
+
const debugtrace = false
func gobuild(t *testing.T, indir string, bargs []string) {
@@ -103,7 +162,7 @@ func TestCovTool(t *testing.T) {
if !goexperiment.CoverageRedesign {
t.Skipf("stubbed out due to goexperiment.CoverageRedesign=false")
}
- dir := t.TempDir()
+ dir := tempDir(t)
if testing.Short() {
t.Skip()
}
@@ -122,10 +181,8 @@ func TestCovTool(t *testing.T) {
flags := []string{"-covermode=atomic"}
s.exepath3, s.exedir3 = buildProg(t, "prog1", dir, "atomic", flags)
- // Build the tool.
- s.tool = filepath.Join(dir, "tool.exe")
- args := []string{"build", "-o", s.tool, "."}
- gobuild(t, "", args)
+ // Reuse unit test executable as tool to be tested.
+ s.tool = testcovdata
// Create a few coverage output dirs.
for i := 0; i < 4; i++ {