1
0
mirror of https://github.com/golang/go synced 2024-11-20 06:24:40 -07:00

cmd/vet: parallelize tests

Was 2.3 seconds. Now 1.4 seconds.

Next win would be not running a child process and refactoring main so
it could be called from tests easily. But that would also require
rewriting the errchk written in Perl. This appears to be the last user
of errchk in the tree.

Updates #17751

Change-Id: Id7c3cec76f438590789b994e756f55b5397be07f
Reviewed-on: https://go-review.googlesource.com/32754
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Brad Fitzpatrick 2016-11-04 19:12:09 +00:00
parent 2b445c7645
commit e017802597
15 changed files with 94 additions and 36 deletions

View File

@ -0,0 +1 @@
package testdata

View File

@ -13,6 +13,7 @@ import (
"os/exec"
"path/filepath"
"runtime"
"sync"
"testing"
)
@ -40,19 +41,22 @@ func MustHavePerl(t *testing.T) {
}
var (
buildMu sync.Mutex // guards following
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) {
testenv.MustHaveGoBuild(t)
MustHavePerl(t)
buildMu.Lock()
defer buildMu.Unlock()
if built {
return
}
if failed {
t.Skip("cannot run on this environment")
}
testenv.MustHaveGoBuild(t)
MustHavePerl(t)
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", binary)
output, err := cmd.CombinedOutput()
if err != nil {
@ -83,52 +87,104 @@ func Vet(t *testing.T, files []string) {
// rm testvet
//
// TestVet tests self-contained files in testdata/*.go.
//
// If a file contains assembly or has inter-dependencies, it should be
// in its own test, like TestVetAsm, TestDivergentPackagesExamples,
// etc below.
func TestVet(t *testing.T) {
Build(t)
t.Parallel()
// errchk ./testvet
gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
if err != nil {
t.Fatal(err)
}
asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
wide := runtime.GOMAXPROCS(0)
if wide > len(gos) {
wide = len(gos)
}
batch := make([][]string, wide)
for i, file := range gos {
batch[i%wide] = append(batch[i%wide], file)
}
for i, files := range batch {
files := files
t.Run(fmt.Sprint(i), func(t *testing.T) {
t.Parallel()
t.Logf("files: %q", files)
Vet(t, files)
})
}
}
func TestVetAsm(t *testing.T) {
Build(t)
asmDir := filepath.Join(dataDir, "asm")
gos, err := filepath.Glob(filepath.Join(asmDir, "*.go"))
if err != nil {
t.Fatal(err)
}
files := append(gos, asms...)
Vet(t, files)
asms, err := filepath.Glob(filepath.Join(asmDir, "*.s"))
if err != nil {
t.Fatal(err)
}
t.Parallel()
// errchk ./testvet
Vet(t, append(gos, asms...))
}
func TestDivergentPackagesExamples(t *testing.T) {
func TestVetDirs(t *testing.T) {
t.Parallel()
Build(t)
// errchk ./testvet
Vet(t, []string{"testdata/divergent"})
}
func TestIncompleteExamples(t *testing.T) {
Build(t)
// errchk ./testvet
Vet(t, []string{"testdata/incomplete/examples_test.go"})
for _, dir := range []string{
"testingpkg",
"divergent",
"buildtag",
"incomplete", // incomplete examples
} {
dir := dir
t.Run(dir, func(t *testing.T) {
t.Parallel()
gos, err := filepath.Glob(filepath.Join("testdata", dir, "*.go"))
if err != nil {
t.Fatal(err)
}
Vet(t, gos)
})
}
}
func run(c *exec.Cmd, t *testing.T) bool {
output, err := c.CombinedOutput()
os.Stderr.Write(output)
if err != nil {
t.Logf("vet output:\n%s", output)
t.Fatal(err)
}
// Errchk delights by not returning non-zero status if it finds errors, so we look at the output.
// It prints "BUG" if there is a failure.
if !c.ProcessState.Success() {
t.Logf("vet output:\n%s", output)
return false
}
return !bytes.Contains(output, []byte("BUG"))
ok := !bytes.Contains(output, []byte("BUG"))
if !ok {
t.Logf("vet output:\n%s", output)
}
return ok
}
// TestTags verifies that the -tags argument controls which files to check.
func TestTags(t *testing.T) {
t.Parallel()
Build(t)
for _, tag := range []string{"testtag", "x testtag y", "x,testtag,y"} {
tag := tag
t.Run(tag, func(t *testing.T) {
t.Parallel()
t.Logf("-tags=%s", tag)
args := []string{
"-tags=" + tag,
@ -147,5 +203,6 @@ func TestTags(t *testing.T) {
if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
t.Error("file2 was included, should be excluded")
}
})
}
}