Skip to content

Commit 39d1db1

Browse files
authored
Fix config_server_test flakiness (#5175)
1 parent bc56b01 commit 39d1db1

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

internal/configconverter/config_server.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ import (
3838
const (
3939
configServerEnabledEnvVar = "SPLUNK_DEBUG_CONFIG_SERVER"
4040
configServerPortEnvVar = "SPLUNK_DEBUG_CONFIG_SERVER_PORT"
41-
defaultConfigServerEndpoint = "localhost:55554"
41+
defaultConfigServerPort = "55554"
42+
defaultConfigServerEndpoint = "localhost:" + defaultConfigServerPort
4243
effectivePath = "/debug/configz/effective"
4344
initialPath = "/debug/configz/initial"
4445
)
@@ -58,7 +59,6 @@ type ConfigServer struct {
5859
initial map[string]any
5960
effective map[string]any
6061
server *http.Server
61-
doneCh chan struct{}
6262
initialMutex sync.RWMutex
6363
effectiveMutex sync.RWMutex
6464
wg sync.WaitGroup
@@ -73,7 +73,6 @@ func NewConfigServer() *ConfigServer {
7373
effectiveMutex: sync.RWMutex{},
7474
wg: sync.WaitGroup{},
7575
once: sync.Once{},
76-
doneCh: make(chan struct{}),
7776
}
7877

7978
mux := http.NewServeMux()
@@ -156,8 +155,6 @@ func (cs *ConfigServer) start() {
156155
}
157156

158157
go func() {
159-
defer close(cs.doneCh)
160-
161158
httpErr := cs.server.Serve(listener)
162159
if httpErr != http.ErrServerClosed {
163160
log.Print(fmt.Errorf("config server error: %w", httpErr).Error())
@@ -166,15 +163,17 @@ func (cs *ConfigServer) start() {
166163

167164
go func() {
168165
cs.wg.Wait()
169-
if cs.server != nil {
170-
_ = cs.server.Close()
171-
}
166+
_ = cs.server.Close()
172167

173168
}()
174169

175170
})
176171
}
177172

173+
// OnShutdown doesn't guarantee that server is down. The server is stopped when
174+
// the number of OnShutdown calls match the number of OnNew calls. The actual
175+
// shutdown time is non-deterministic since it happens in a goroutine that
176+
// was waiting for the last OnShutdown call.
178177
func (cs *ConfigServer) OnShutdown() {
179178
cs.wg.Done()
180179
}

internal/configconverter/config_server_test.go

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ package configconverter
1818
import (
1919
"context"
2020
"io"
21+
"net"
2122
"net/http"
2223
"os"
2324
"strconv"
2425
"testing"
26+
"time"
2527

2628
"github.com/stretchr/testify/assert"
2729
"github.com/stretchr/testify/require"
@@ -39,7 +41,9 @@ func TestConfigServer_RequireEnvVar(t *testing.T) {
3941
cs := NewConfigServer()
4042
require.NotNil(t, cs)
4143
cs.OnNew()
42-
t.Cleanup(cs.OnShutdown)
44+
t.Cleanup(func() {
45+
shutdownAndWaitForPort(t, cs, defaultConfigServerPort)
46+
})
4347
require.NoError(t, cs.Convert(context.Background(), confmap.NewFromStringMap(initial)))
4448

4549
client := &http.Client{}
@@ -90,18 +94,16 @@ func TestConfigServer_EnvVar(t *testing.T) {
9094
}()
9195
}
9296

97+
actualServerPort := defaultConfigServerPort
98+
if tt.portEnvVar != "" {
99+
actualServerPort = tt.portEnvVar
100+
}
93101
cs := NewConfigServer()
94102
require.NotNil(t, cs)
95103
cs.OnNew()
96104

97105
require.NoError(t, cs.Convert(context.Background(), confmap.NewFromStringMap(initial)))
98-
defer func() {
99-
cs.OnShutdown() // Call shutdown even if the server is not up.
100-
if !tt.serverDown {
101-
// Wait for the server to shutdown. Otherwise the port might be still in use.
102-
<-cs.doneCh
103-
}
104-
}()
106+
defer shutdownAndWaitForPort(t, cs, actualServerPort)
105107

106108
endpoint := tt.endpoint
107109
if endpoint == "" {
@@ -154,7 +156,9 @@ func TestConfigServer_Serve(t *testing.T) {
154156
cs := NewConfigServer()
155157
require.NotNil(t, cs)
156158
cs.OnNew()
157-
t.Cleanup(cs.OnShutdown)
159+
t.Cleanup(func() {
160+
shutdownAndWaitForPort(t, cs, defaultConfigServerPort)
161+
})
158162

159163
cs.OnRetrieve("scheme", initial)
160164
require.NoError(t, cs.Convert(context.Background(), confmap.NewFromStringMap(initial)))
@@ -225,3 +229,15 @@ func TestSimpleRedact(t *testing.T) {
225229
"X-SF-Token": "<redacted>",
226230
}, result)
227231
}
232+
233+
func shutdownAndWaitForPort(t *testing.T, cs *ConfigServer, port string) {
234+
cs.OnShutdown()
235+
require.Eventually(t, func() bool {
236+
ln, err := net.Listen("tcp", "localhost:"+port)
237+
if err == nil {
238+
ln.Close()
239+
return true
240+
}
241+
return false
242+
}, 5*time.Second, 200*time.Millisecond)
243+
}

0 commit comments

Comments
 (0)