@@ -17,7 +17,7 @@ import (
1717// buildRudderServerBinary builds the rudder-server binary and returns its path.
1818func buildRudderServerBinary (t * testing.T , binaryPath string ) {
1919 name := "testbinary"
20- buildCmd := exec .Command ("go" , "build" , "-o" , binaryPath , "../../main.go" )
20+ buildCmd := exec .Command ("go" , "build" , "-cover" , "- o" , binaryPath , "../../main.go" )
2121 buildCmd .Stderr = os .Stderr
2222 buildCmd .Stdout = os .Stdout
2323 if err := buildCmd .Run (); err != nil {
@@ -26,17 +26,31 @@ func buildRudderServerBinary(t *testing.T, binaryPath string) {
2626}
2727
2828// startRudderServer starts a rudder-server process with the given environment configuration in a separate goroutine managed by the provided errgroup.Group.
29- func startRudderServer (ctx context.Context , g * errgroup.Group , name , binaryPath string , configs map [string ]string ) {
29+ // It sends SIGTERM when the context is cancelled to allow graceful shutdown and proper coverage data collection.
30+ func startRudderServer (t * testing.T , ctx context.Context , g * errgroup.Group , name , binaryPath string , configs map [string ]string ) {
31+ coverDir := t .TempDir ()
32+ configs ["GOCOVERDIR" ] = coverDir
33+ // Don't use exec.CommandContext - it sends SIGKILL on context cancellation,
34+ // which prevents the process from writing coverage data.
35+ cmd := exec .Command (binaryPath )
36+ cmd .Env = append (os .Environ (), lo .MapToSlice (configs , func (k , v string ) string {
37+ return config .ConfigKeyToEnv (config .DefaultEnvPrefix , k ) + "=" + v
38+ })... )
39+ cmd .Stderr = os .Stderr
40+ cmd .Stdout = os .Stdout
41+ if err := cmd .Start (); err != nil {
42+ t .Fatalf ("server %q: failed to start: %v" , name , err )
43+ }
44+
3045 g .Go (func () error {
31- cmd := exec .CommandContext (ctx , binaryPath )
32- cmd .Env = append (os .Environ (), lo .MapToSlice (configs , func (k , v string ) string {
33- return config .ConfigKeyToEnv (config .DefaultEnvPrefix , k ) + "=" + v
34- })... )
35- cmd .Stderr = os .Stderr
36- cmd .Stdout = os .Stdout
37- if err := cmd .Start (); err != nil {
38- return fmt .Errorf ("server %q: failed to start: %w" , name , err )
46+ defer convertCoverageData (t , coverDir , name + "-profile.out" )
47+
48+ // Wait for context cancellation, then send SIGTERM for graceful shutdown
49+ <- ctx .Done ()
50+ if err := cmd .Process .Signal (syscall .SIGTERM ); err != nil {
51+ t .Logf ("server %q: failed to send SIGTERM: %v" , name , err )
3952 }
53+
4054 if err := cmd .Wait (); err != nil {
4155 if exitErr , ok := err .(* exec.ExitError ); ok {
4256 if status , ok := exitErr .Sys ().(syscall.WaitStatus ); ok {
@@ -50,3 +64,11 @@ func startRudderServer(ctx context.Context, g *errgroup.Group, name, binaryPath
5064 return nil
5165 })
5266}
67+
68+ func convertCoverageData (t * testing.T , coverDir , outputFile string ) {
69+ cmd := exec .Command ("go" , "tool" , "covdata" , "textfmt" , "-i=" + coverDir , "-o=" + outputFile )
70+ cmd .Stderr = os .Stderr
71+ if err := cmd .Run (); err != nil {
72+ t .Logf ("failed to convert coverage data: %v" , err )
73+ }
74+ }
0 commit comments