integration_test.go: use custom parallel test code
The t.Parallel method does not interact well with the -failfast flag.
See golang/go#30522.
Instead, start off tests ourselves in a goroutine.
Doing it this way allows the -failfast flag to take effect sooner.
One nice benefit of this change is that the test output is cleaner:
Before:
<<<
=== RUN Test
=== RUN Test/Go1.9.7
=== RUN Test/Go1.9.7/TestNormal
=== PAUSE Test/Go1.9.7/TestNormal
=== RUN Test/Go1.9.7/TestPureGo
=== PAUSE Test/Go1.9.7/TestPureGo
=== RUN Test/Go1.9.7/TestReflect
=== PAUSE Test/Go1.9.7/TestReflect
=== CONT Test/Go1.9.7/TestNormal
=== CONT Test/Go1.9.7/TestReflect
=== CONT Test/Go1.9.7/TestPureGo
=== RUN Test/Go1.10.8
=== RUN Test/Go1.10.8/TestNormal
=== PAUSE Test/Go1.10.8/TestNormal
=== RUN Test/Go1.10.8/TestPureGo
=== PAUSE Test/Go1.10.8/TestPureGo
=== RUN Test/Go1.10.8/TestReflect
=== PAUSE Test/Go1.10.8/TestReflect
=== CONT Test/Go1.10.8/TestNormal
=== CONT Test/Go1.10.8/TestReflect
=== CONT Test/Go1.10.8/TestPureGo
=== RUN Test/Go1.11.6
=== RUN Test/Go1.11.6/TestNormal
=== PAUSE Test/Go1.11.6/TestNormal
=== RUN Test/Go1.11.6/TestPureGo
=== PAUSE Test/Go1.11.6/TestPureGo
=== RUN Test/Go1.11.6/TestReflect
=== PAUSE Test/Go1.11.6/TestReflect
=== CONT Test/Go1.11.6/TestNormal
=== CONT Test/Go1.11.6/TestReflect
=== CONT Test/Go1.11.6/TestPureGo
=== RUN Test/Go1.12.1
=== RUN Test/Go1.12.1/TestNormal
=== PAUSE Test/Go1.12.1/TestNormal
=== RUN Test/Go1.12.1/TestPureGo
=== PAUSE Test/Go1.12.1/TestPureGo
=== RUN Test/Go1.12.1/TestReflect
=== PAUSE Test/Go1.12.1/TestReflect
=== RUN Test/Go1.12.1/TestProto1Legacy
=== PAUSE Test/Go1.12.1/TestProto1Legacy
=== RUN Test/Go1.12.1/TestProtocGenGo
=== PAUSE Test/Go1.12.1/TestProtocGenGo
=== RUN Test/Go1.12.1/TestProtocGenGoGRPC
=== PAUSE Test/Go1.12.1/TestProtocGenGoGRPC
=== CONT Test/Go1.12.1/TestNormal
=== CONT Test/Go1.12.1/TestProto1Legacy
=== CONT Test/Go1.12.1/TestProtocGenGoGRPC
=== CONT Test/Go1.12.1/TestProtocGenGo
=== CONT Test/Go1.12.1/TestReflect
=== CONT Test/Go1.12.1/TestPureGo
=== RUN Test/ConformanceTests
=== RUN Test/GeneratedGoFiles
=== RUN Test/FormattedGoFiles
=== RUN Test/CommittedGitChanges
=== RUN Test/TrackedGitFiles
--- PASS: Test (509.59s)
--- PASS: Test/Go1.9.7 (0.00s)
--- PASS: Test/Go1.9.7/TestReflect (100.81s)
--- PASS: Test/Go1.9.7/TestNormal (100.88s)
--- PASS: Test/Go1.9.7/TestPureGo (56.93s)
--- PASS: Test/Go1.10.8 (0.00s)
--- PASS: Test/Go1.10.8/TestNormal (64.85s)
--- PASS: Test/Go1.10.8/TestReflect (65.20s)
--- PASS: Test/Go1.10.8/TestPureGo (36.14s)
--- PASS: Test/Go1.11.6 (0.00s)
--- PASS: Test/Go1.11.6/TestReflect (59.69s)
--- PASS: Test/Go1.11.6/TestNormal (60.25s)
--- PASS: Test/Go1.11.6/TestPureGo (34.17s)
--- PASS: Test/Go1.12.1 (0.00s)
--- PASS: Test/Go1.12.1/TestProto1Legacy (59.41s)
--- PASS: Test/Go1.12.1/TestNormal (59.87s)
--- PASS: Test/Go1.12.1/TestProtocGenGo (3.55s)
--- PASS: Test/Go1.12.1/TestProtocGenGoGRPC (4.12s)
--- PASS: Test/Go1.12.1/TestReflect (60.10s)
--- PASS: Test/Go1.12.1/TestPureGo (60.66s)
--- PASS: Test/ConformanceTests (0.78s)
--- PASS: Test/GeneratedGoFiles (8.99s)
--- PASS: Test/FormattedGoFiles (2.64s)
--- PASS: Test/CommittedGitChanges (0.10s)
--- PASS: Test/TrackedGitFiles (0.00s)
PASS
>>>
After:
<<<
=== RUN Test
=== RUN Test/Go1.9.7/PureGo
=== RUN Test/Go1.9.7/Normal
=== RUN Test/Go1.9.7/Reflect
=== RUN Test/Go1.10.8/Normal
=== RUN Test/Go1.10.8/PureGo
=== RUN Test/Go1.10.8/Reflect
=== RUN Test/Go1.11.6/Normal
=== RUN Test/Go1.11.6/PureGo
=== RUN Test/Go1.11.6/Reflect
=== RUN Test/Go1.12.1/Normal
=== RUN Test/Go1.12.1/PureGo
=== RUN Test/Go1.12.1/Reflect
=== RUN Test/Go1.12.1/Proto1Legacy
=== RUN Test/Go1.12.1/ProtocGenGo
=== RUN Test/Go1.12.1/ProtocGenGoGRPC
=== RUN Test/ConformanceTests
=== RUN Test/GeneratedGoFiles
=== RUN Test/FormattedGoFiles
=== RUN Test/CommittedGitChanges
--- PASS: Test (182.87s)
--- PASS: Test/Go1.9.7/PureGo (72.17s)
--- PASS: Test/Go1.9.7/Normal (72.59s)
--- PASS: Test/Go1.10.8/Normal (8.03s)
--- PASS: Test/Go1.10.8/PureGo (8.03s)
--- PASS: Test/Go1.10.8/Reflect (8.34s)
--- PASS: Test/Go1.11.6/Normal (10.70s)
--- PASS: Test/Go1.11.6/PureGo (8.21s)
--- PASS: Test/Go1.11.6/Reflect (8.77s)
--- PASS: Test/Go1.12.1/Normal (7.41s)
--- PASS: Test/Go1.12.1/PureGo (6.52s)
--- PASS: Test/Go1.12.1/Reflect (6.04s)
--- PASS: Test/Go1.12.1/Proto1Legacy (6.96s)
--- PASS: Test/Go1.12.1/ProtocGenGo (1.15s)
--- PASS: Test/Go1.12.1/ProtocGenGoGRPC (2.43s)
--- PASS: Test/Go1.9.7/Reflect (88.47s)
--- PASS: Test/ConformanceTests (1.81s)
--- PASS: Test/GeneratedGoFiles (16.28s)
--- PASS: Test/FormattedGoFiles (3.17s)
--- PASS: Test/CommittedGitChanges (0.17s)
PASS
>>>
Change-Id: I777ffe3f4d5f6407c87e3866cbaa890017204cba
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/185877
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/integration_test.go b/integration_test.go
index bc3944d..433de7c 100644
--- a/integration_test.go
+++ b/integration_test.go
@@ -22,6 +22,7 @@
"regexp"
"runtime"
"strings"
+ "sync"
"testing"
"time"
)
@@ -55,26 +56,35 @@
t.SkipNow()
}
- for _, v := range golangVersions {
- t.Run("Go"+v, func(t *testing.T) {
- runGo := func(label, workDir string, args ...string) {
- args[0] += v
- t.Run(label, func(t *testing.T) {
- t.Parallel()
+ var wg sync.WaitGroup
+ sema := make(chan bool, (runtime.NumCPU()+1)/2)
+ for i := range golangVersions {
+ goVersion := golangVersions[i]
+ goLabel := "Go" + goVersion
+ runGo := func(label, workDir string, args ...string) {
+ wg.Add(1)
+ sema <- true
+ go func() {
+ defer wg.Done()
+ defer func() { <-sema }()
+ t.Run(goLabel+"/"+label, func(t *testing.T) {
+ args[0] += goVersion
mustRunCommand(t, workDir, args...)
})
- }
- workDir := filepath.Join(goPath, "src", modulePath)
- runGo("TestNormal", workDir, "go", "test", "-race", "./...")
- runGo("TestPureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...")
- runGo("TestReflect", workDir, "go", "test", "-race", "-tags", "protoreflect", "./...")
- if v == golangLatest {
- runGo("TestProto1Legacy", workDir, "go", "test", "-race", "-tags", "proto1_legacy", "./...")
- runGo("TestProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test")
- runGo("TestProtocGenGoGRPC", "cmd/protoc-gen-go-grpc/testdata", "go", "test")
- }
- })
+ }()
+ }
+
+ workDir := filepath.Join(goPath, "src", modulePath)
+ runGo("Normal", workDir, "go", "test", "-race", "./...")
+ runGo("PureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...")
+ runGo("Reflect", workDir, "go", "test", "-race", "-tags", "protoreflect", "./...")
+ if goVersion == golangLatest {
+ runGo("Proto1Legacy", workDir, "go", "test", "-race", "-tags", "proto1_legacy", "./...")
+ runGo("ProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test")
+ runGo("ProtocGenGoGRPC", "cmd/protoc-gen-go-grpc/testdata", "go", "test")
+ }
}
+ wg.Wait()
t.Run("ConformanceTests", func(t *testing.T) {
driverPath := filepath.Join("internal", "cmd", "conformance")