From ebd96933c11d67997d1609c06b0cf076067a4f50 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 21 Sep 2015 11:06:43 -0700 Subject: [PATCH] cmd/vet: build the binary only once in the test Recent changes caused vet to build the binary for each Test function. This is wasteful and will become only more so as more tests are added. Use testing.Main to build only once. Verified that compilation errors still appear if the binary cannot be built. Before: real 0m11.169s user 0m18.328s sys 0m2.152s After: real 0m5.132s user 0m9.404s sys 0m1.168s Of course if the compiler were fast we might not notice, but vet is a big program and growing bigger all the time, as are the tests. Change-Id: I209a8fdcace94bc5cec946f5dd365d7191f44c02 Reviewed-on: https://go-review.googlesource.com/14822 Reviewed-by: Brad Fitzpatrick --- src/cmd/vet/vet_test.go | 62 ++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index 7508193659..ea402ff9b2 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -10,6 +10,8 @@ package main_test import ( "bytes" + "flag" + "fmt" "os" "os/exec" "path/filepath" @@ -22,20 +24,47 @@ const ( binary = "testvet.exe" ) -func CanRun(t *testing.T) bool { - // Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk. +// We implement TestMain so remove the test binary when all is done. +func TestMain(m *testing.M) { + flag.Parse() + result := m.Run() + os.Remove(binary) + os.Exit(result) +} + +func CanRun() bool { switch runtime.GOOS { case "plan9", "windows": - t.Skip("skipping test; no Perl on %q", runtime.GOOS) + // No Perl installed, can't run errcheck. + return false + case "nacl": + // Minimal and problematic file system. return false } return true } +var ( + built = false // We have built the binary. + failed = false // We have failed to build the binary, don't try again. +) + func Build(t *testing.T) { - // go build + if built { + return + } + if !CanRun() || failed { + t.Skip("cannot run on this environment") + return + } cmd := exec.Command("go", "build", "-o", binary) - run(cmd, t) + output, err := cmd.CombinedOutput() + if err != nil { + failed = true + fmt.Fprintf(os.Stderr, "%s\n", output) + t.Fatal(err) + } + built = true } func Vet(t *testing.T, files []string) { @@ -58,11 +87,7 @@ func Vet(t *testing.T, files []string) { // func TestVet(t *testing.T) { - if !CanRun(t) { - t.Skip("cannot run on this environment") - } Build(t) - defer os.Remove(binary) // errchk ./testvet gos, err := filepath.Glob(filepath.Join(dataDir, "*.go")) @@ -78,23 +103,13 @@ func TestVet(t *testing.T) { } func TestDivergentPackagesExamples(t *testing.T) { - if !CanRun(t) { - t.Skip("cannot run on this environment") - } Build(t) - defer os.Remove(binary) - // errchk ./testvet Vet(t, []string{"testdata/divergent/buf.go", "testdata/divergent/buf_test.go"}) } func TestIncompleteExamples(t *testing.T) { - if !CanRun(t) { - t.Skip("cannot run on this environment") - } Build(t) - defer os.Remove(binary) - // errchk ./testvet Vet(t, []string{"testdata/incomplete/examples_test.go"}) } @@ -115,18 +130,13 @@ func run(c *exec.Cmd, t *testing.T) bool { // TestTags verifies that the -tags argument controls which files to check. func TestTags(t *testing.T) { - // go build - cmd := exec.Command("go", "build", "-o", binary) - run(cmd, t) - - defer os.Remove(binary) - + Build(t) args := []string{ "-tags=testtag", "-v", // We're going to look at the files it examines. "testdata/tagtest", } - cmd = exec.Command("./"+binary, args...) + cmd := exec.Command("./"+binary, args...) output, err := cmd.CombinedOutput() if err != nil { t.Fatal(err)