aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/cover
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2018-12-05 17:24:41 -0800
committerIan Lance Taylor <iant@golang.org>2018-12-06 22:06:55 +0000
commit4a801cdd319dc25a2bcdced0b70377c2dfa1464f (patch)
treea224e818ddab955a967c07cb3a893590d553b1e7 /src/cmd/cover
parentec0077c54d6261ba5cbab2c5dc2e80345068233f (diff)
downloadgo-4a801cdd319dc25a2bcdced0b70377c2dfa1464f.tar.gz
go-4a801cdd319dc25a2bcdced0b70377c2dfa1464f.zip
cmd/cover: run tests in parallel, don't change source directory
This speeds up the cmd/cover testsuite by about 40% on my laptop. Updates #26473 Updates #28386 Change-Id: I853b1b3b8c98dc89440f7b7bf5c0ade1d3d66802 Reviewed-on: https://go-review.googlesource.com/c/152817 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Diffstat (limited to 'src/cmd/cover')
-rw-r--r--src/cmd/cover/cover_test.go147
1 files changed, 102 insertions, 45 deletions
diff --git a/src/cmd/cover/cover_test.go b/src/cmd/cover/cover_test.go
index 8eb7124aad..a374dc4e9b 100644
--- a/src/cmd/cover/cover_test.go
+++ b/src/cmd/cover/cover_test.go
@@ -19,43 +19,103 @@ import (
"path/filepath"
"regexp"
"strings"
+ "sync"
"testing"
)
const (
// Data directory, also the package directory for the test.
testdata = "testdata"
-
- // Binaries we compile.
- testcover = "./testcover.exe"
)
var (
- // Files we use.
+ // Input files.
testMain = filepath.Join(testdata, "main.go")
testTest = filepath.Join(testdata, "test.go")
- coverInput = filepath.Join(testdata, "test_line.go")
- coverOutput = filepath.Join(testdata, "test_cover.go")
coverProfile = filepath.Join(testdata, "profile.cov")
// The HTML test files are in a separate directory
// so they are a complete package.
- htmlProfile = filepath.Join(testdata, "html", "html.cov")
- htmlHTML = filepath.Join(testdata, "html", "html.html")
- htmlGolden = filepath.Join(testdata, "html", "html.golden")
+ htmlGolden = filepath.Join(testdata, "html", "html.golden")
+
+ // Temporary files.
+ tmpTestMain string
+ coverInput string
+ coverOutput string
+ htmlProfile string
+ htmlHTML string
+)
+
+var (
+ // testTempDir is a temporary directory created in TestMain.
+ testTempDir string
+
+ // testcover is a newly built version of the cover program.
+ testcover string
+
+ // testcoverErr records an error building testcover.
+ testcoverErr error
+
+ // testcoverOnce is used to build testcover once.
+ testcoverOnce sync.Once
)
var debug = flag.Bool("debug", false, "keep rewritten files for debugging")
+// We use TestMain to set up a temporary directory and remove it when
+// the tests are done.
+func TestMain(m *testing.M) {
+ dir, err := ioutil.TempDir("", "gotestcover")
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
+ testTempDir = dir
+
+ tmpTestMain = filepath.Join(dir, "main.go")
+ coverInput = filepath.Join(dir, "test_line.go")
+ coverOutput = filepath.Join(dir, "test_cover.go")
+ htmlProfile = filepath.Join(dir, "html.cov")
+ htmlHTML = filepath.Join(dir, "html.html")
+
+ status := m.Run()
+
+ if !*debug {
+ os.RemoveAll(dir)
+ }
+
+ os.Exit(status)
+}
+
+// buildCover builds a version of the cover program for testing.
+// This ensures that "go test cmd/cover" tests the current cmd/cover.
+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
+ })
+ if testcoverErr != nil {
+ t.Fatal("failed to build testcover program:", testcoverErr)
+ }
+}
+
// Run this shell script, but do it in Go so it can be run by "go test".
//
// replace the word LINE with the line number < testdata/test.go > testdata/test_line.go
-// go build -o ./testcover
-// ./testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
+// go build -o testcover
+// testcover -mode=count -var=CoverTest -o ./testdata/test_cover.go testdata/test_line.go
// go run ./testdata/main.go ./testdata/test.go
//
func TestCover(t *testing.T) {
- testenv.MustHaveGoBuild(t)
+ t.Parallel()
+ testenv.MustHaveGoRun(t)
+ buildCover(t)
// Read in the test file (testTest) and write it, with LINEs specified, to coverInput.
file, err := ioutil.ReadFile(testTest)
@@ -81,29 +141,22 @@ func TestCover(t *testing.T) {
t.Fatal(err)
}
- // defer removal of test_line.go
- if !*debug {
- defer os.Remove(coverInput)
- }
-
- // go build -o testcover
- cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover)
+ // testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go
+ cmd := exec.Command(testcover, "-mode=count", "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest", "-o", coverOutput, coverInput)
run(cmd, t)
- // defer removal of testcover
- defer os.Remove(testcover)
-
- // ./testcover -mode=count -var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest -o ./testdata/test_cover.go testdata/test_line.go
- cmd = exec.Command(testcover, "-mode=count", "-var=thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest", "-o", coverOutput, coverInput)
- run(cmd, t)
-
- // defer removal of ./testdata/test_cover.go
- if !*debug {
- defer os.Remove(coverOutput)
+ // Copy testmain to testTempDir, so that it is in the same directory
+ // as coverOutput.
+ b, err := ioutil.ReadFile(testMain)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := ioutil.WriteFile(tmpTestMain, b, 0444); err != nil {
+ t.Fatal(err)
}
// go run ./testdata/main.go ./testdata/test.go
- cmd = exec.Command(testenv.GoToolPath(t), "run", testMain, coverOutput)
+ cmd = exec.Command(testenv.GoToolPath(t), "run", tmpTestMain, coverOutput)
run(cmd, t)
file, err = ioutil.ReadFile(coverOutput)
@@ -131,6 +184,9 @@ func TestCover(t *testing.T) {
// above those declarations, even if they are not part of the block of
// documentation comments.
func TestDirectives(t *testing.T) {
+ t.Parallel()
+ buildCover(t)
+
// Read the source file and find all the directives. We'll keep
// track of whether each one has been seen in the output.
testDirectives := filepath.Join(testdata, "directives.go")
@@ -140,8 +196,8 @@ func TestDirectives(t *testing.T) {
}
sourceDirectives := findDirectives(source)
- // go tool cover -mode=atomic ./testdata/directives.go
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "cover", "-mode=atomic", testDirectives)
+ // testcover -mode=atomic ./testdata/directives.go
+ cmd := exec.Command(testcover, "-mode=atomic", testDirectives)
cmd.Stderr = os.Stderr
output, err := cmd.Output()
if err != nil {
@@ -247,8 +303,10 @@ func findDirectives(source []byte) []directiveInfo {
// Makes sure that `cover -func=profile.cov` reports accurate coverage.
// Issue #20515.
func TestCoverFunc(t *testing.T) {
- // go tool cover -func ./testdata/profile.cov
- cmd := exec.Command(testenv.GoToolPath(t), "tool", "cover", "-func", coverProfile)
+ t.Parallel()
+ buildCover(t)
+ // testcover -func ./testdata/profile.cov
+ cmd := exec.Command(testcover, "-func", coverProfile)
out, err := cmd.Output()
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
@@ -266,19 +324,14 @@ func TestCoverFunc(t *testing.T) {
// Check that cover produces correct HTML.
// Issue #25767.
func TestCoverHTML(t *testing.T) {
- testenv.MustHaveGoBuild(t)
- if !*debug {
- defer os.Remove(testcover)
- defer os.Remove(htmlProfile)
- defer os.Remove(htmlHTML)
- }
- // go build -o testcover
- cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", testcover)
- run(cmd, t)
+ t.Parallel()
+ testenv.MustHaveGoRun(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", "-coverprofile", htmlProfile, "cmd/cover/testdata/html")
run(cmd, t)
- // ./testcover -html testdata/html/html.cov -o testdata/html/html.html
+ // testcover -html testdata/html/html.cov -o testdata/html/html.html
cmd = exec.Command(testcover, "-html", htmlProfile, "-o", htmlHTML)
run(cmd, t)
@@ -303,6 +356,9 @@ func TestCoverHTML(t *testing.T) {
in = false
}
}
+ if scan.Err() != nil {
+ t.Error(scan.Err())
+ }
golden, err := ioutil.ReadFile(htmlGolden)
if err != nil {
t.Fatalf("reading golden file: %v", err)
@@ -331,6 +387,7 @@ func TestCoverHTML(t *testing.T) {
func run(c *exec.Cmd, t *testing.T) {
t.Helper()
+ t.Log("running", c.Args)
c.Stdout = os.Stdout
c.Stderr = os.Stderr
err := c.Run()