@@ -6,74 +6,80 @@ import (
66 "os/exec"
77 "path/filepath"
88 "runtime"
9+ "sync"
910 "testing"
1011
1112 "github.com/stretchr/testify/assert"
1213)
1314
1415// prebuiltBinary holds the path to the pre-built speakeasy binary.
1516// This avoids recompiling on every `go run main.go` call, saving ~20s per invocation.
16- var prebuiltBinary string
17+ var (
18+ prebuiltBinary string
19+ buildOnce sync.Once
20+ buildErr error
21+ )
22+
23+ // ensureBinary builds the speakeasy binary once on first call.
24+ // Subsequent calls return immediately. This is called lazily by execute()
25+ // so that executeI() invocations don't pay the build cost.
26+ func ensureBinary () (string , error ) {
27+ buildOnce .Do (func () {
28+ _ , filename , _ , _ := runtime .Caller (0 )
29+ baseFolder := filepath .Join (filepath .Dir (filename ), ".." )
30+ // Use PID to avoid collision between parallel test runs on the same machine
31+ binaryName := fmt .Sprintf ("speakeasy-test-binary-%d" , os .Getpid ())
32+ if runtime .GOOS == "windows" {
33+ binaryName += ".exe"
34+ }
35+ binaryPath := filepath .Join (os .TempDir (), binaryName )
36+
37+ fmt .Println ("Pre-building speakeasy binary for integration tests..." )
38+ buildCmd := exec .Command ("go" , "build" , "-o" , binaryPath , filepath .Join (baseFolder , "main.go" ))
39+ buildCmd .Dir = baseFolder
40+ buildCmd .Stdout = os .Stdout
41+ buildCmd .Stderr = os .Stderr
42+ if err := buildCmd .Run (); err != nil {
43+ buildErr = fmt .Errorf ("failed to pre-build speakeasy binary: %w" , err )
44+ return
45+ }
46+ prebuiltBinary = binaryPath
47+ fmt .Println ("Pre-built speakeasy binary:" , prebuiltBinary )
48+ })
49+ return prebuiltBinary , buildErr
50+ }
1751
1852// Entrypoint for CLI integration tests
1953func TestMain (m * testing.M ) {
20- // Create a temporary directory
21- if _ , err := os .Stat (tempDir ); err == nil {
22- if err := os .RemoveAll (tempDir ); err != nil {
23- panic (err )
24- }
25- }
54+ testDir := integrationTestsDir ()
2655
27- if err := os .Mkdir (tempDir , 0o755 ); err != nil {
56+ // Create the integrationTests directory (MkdirAll is safe for parallel test processes)
57+ if err := os .MkdirAll (testDir , 0o755 ); err != nil {
2858 panic (err )
2959 }
3060
31- // Pre-build the speakeasy binary once to avoid ~20s compilation overhead per test
32- _ , filename , _ , _ := runtime .Caller (0 )
33- baseFolder := filepath .Join (filepath .Dir (filename ), ".." )
34- binaryName := "speakeasy-test-binary"
35- if runtime .GOOS == "windows" {
36- binaryName += ".exe"
37- }
38- binaryPath := filepath .Join (os .TempDir (), binaryName )
39-
40- fmt .Println ("Pre-building speakeasy binary for integration tests..." )
41- buildCmd := exec .Command ("go" , "build" , "-o" , binaryPath , filepath .Join (baseFolder , "main.go" ))
42- buildCmd .Dir = baseFolder
43- buildCmd .Stdout = os .Stdout
44- buildCmd .Stderr = os .Stderr
45- if err := buildCmd .Run (); err != nil {
46- panic (fmt .Sprintf ("failed to pre-build speakeasy binary: %v" , err ))
47- }
48- prebuiltBinary = binaryPath
49- fmt .Println ("Pre-built speakeasy binary:" , prebuiltBinary )
61+ code := m .Run ()
5062
51- // Defer the removal of the temp directory and binary
52- defer func () {
53- if err := os .RemoveAll (tempDir ); err != nil {
54- panic (err )
55- }
63+ // Cleanup must happen before os.Exit (defer is not executed with os.Exit)
64+ if prebuiltBinary != "" {
5665 os .Remove (prebuiltBinary )
57- }()
66+ }
5867
59- code := m .Run ()
6068 os .Exit (code )
6169}
6270
6371func setupTestDir (t * testing.T ) string {
6472 t .Helper ()
65- _ , filename , _ , _ := runtime .Caller (0 )
66- workingDir := filepath .Dir (filename )
67- temp , err := createTempDir (workingDir )
73+ temp , err := createTempDir ("" )
6874 assert .NoError (t , err )
69- registerCleanup (t , workingDir , temp )
75+ registerCleanup (t , temp )
7076
7177 return temp
7278}
7379
74- func registerCleanup (t * testing.T , workingDir string , temp string ) {
80+ func registerCleanup (t * testing.T , temp string ) {
7581 t .Helper ()
7682 t .Cleanup (func () {
77- os .RemoveAll (filepath . Join ( workingDir , temp ) )
83+ os .RemoveAll (temp )
7884 })
7985}
0 commit comments