"os/exec"
"path/filepath"
"runtime"
+ "sync"
"testing"
)
}
var (
- built = false // We have built the binary.
- failed = false // We have failed to build the binary, don't try again.
+ 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 {
// 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"))
- if err != nil {
- t.Fatal(err)
+ 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)
+ })
}
- files := append(gos, asms...)
- Vet(t, files)
}
-func TestDivergentPackagesExamples(t *testing.T) {
+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)
+ }
+ asms, err := filepath.Glob(filepath.Join(asmDir, "*.s"))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ t.Parallel()
// errchk ./testvet
- Vet(t, []string{"testdata/divergent"})
+ Vet(t, append(gos, asms...))
}
-func TestIncompleteExamples(t *testing.T) {
+func TestVetDirs(t *testing.T) {
+ t.Parallel()
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"} {
- t.Logf("-tags=%s", tag)
- args := []string{
- "-tags=" + tag,
- "-v", // We're going to look at the files it examines.
- "testdata/tagtest",
- }
- cmd := exec.Command("./"+binary, args...)
- output, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatal(err)
- }
- // file1 has testtag and file2 has !testtag.
- if !bytes.Contains(output, []byte(filepath.Join("tagtest", "file1.go"))) {
- t.Error("file1 was excluded, should be included")
- }
- if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
- t.Error("file2 was included, should be excluded")
- }
+ tag := tag
+ t.Run(tag, func(t *testing.T) {
+ t.Parallel()
+ t.Logf("-tags=%s", tag)
+ args := []string{
+ "-tags=" + tag,
+ "-v", // We're going to look at the files it examines.
+ "testdata/tagtest",
+ }
+ cmd := exec.Command("./"+binary, args...)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatal(err)
+ }
+ // file1 has testtag and file2 has !testtag.
+ if !bytes.Contains(output, []byte(filepath.Join("tagtest", "file1.go"))) {
+ t.Error("file1 was excluded, should be included")
+ }
+ if bytes.Contains(output, []byte(filepath.Join("tagtest", "file2.go"))) {
+ t.Error("file2 was included, should be excluded")
+ }
+ })
}
}