Skip to content

Commit 67f2f6b

Browse files
authored
test: fix flaky tests in proxylistener (#4055)
test: fix flaky tests in proxylistener Signed-off-by: Sandor Szücs <sandor.szuecs@zalando.de>
1 parent 5517405 commit 67f2f6b

1 file changed

Lines changed: 37 additions & 8 deletions

File tree

proxylistener/proxylistener_test.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"testing"
1111
"time"
1212

13-
"github.com/pires/go-proxyproto"
13+
proxyproto "github.com/pires/go-proxyproto"
1414
)
1515

1616
// type testListener struct {
@@ -50,6 +50,7 @@ func createProxyClient(proxyAddr, destAddr string, destPort int) *http.Client {
5050

5151
return &http.Client{
5252
Transport: &http.Transport{
53+
DisableKeepAlives: true, // each request uses its own connection; prevents idle-connection races
5354
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
5455
conn, err := dialer.Dial(network, proxyAddr)
5556
if err != nil {
@@ -88,6 +89,7 @@ func createBogusProxyClient(proxyAddr, destAddr string, destPort int, version by
8889

8990
cli := &http.Client{
9091
Transport: &http.Transport{
92+
DisableKeepAlives: true, // each request uses its own connection; prevents idle-connection races
9193
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
9294
conn, err := dialer.Dial(network, proxyAddr)
9395
if err != nil {
@@ -199,11 +201,16 @@ func TestProxyListenerWithProxyClient(t *testing.T) {
199201

200202
client := createProxyClient(addr, "10.0.0.5", 8080)
201203

204+
// shutdownCH is closed after client.Do returns so that srv.Shutdown
205+
// is only called once the request has completed, not on a fixed timer.
206+
shutdownCH := make(chan struct{})
202207
waitShutdownCH := make(chan struct{})
203208
go func() {
204-
time.Sleep(time.Second)
209+
<-shutdownCH
205210
t.Log("Start shutdown")
206-
if err := srv.Shutdown(context.Background()); err != nil {
211+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
212+
defer cancel()
213+
if err := srv.Shutdown(ctx); err != nil {
207214
t.Logf("Failed to graceful shutdown: %v", err)
208215
}
209216
close(waitShutdownCH)
@@ -224,9 +231,13 @@ func TestProxyListenerWithProxyClient(t *testing.T) {
224231
}
225232
req.Host = tt.host
226233
rsp, err := client.Do(req)
234+
close(shutdownCH) // trigger shutdown now that request has completed or failed
227235
if err != nil && !tt.wantErr {
228236
t.Fatalf("Failed to get response: %v", err)
229237
}
238+
if rsp != nil {
239+
rsp.Body.Close()
240+
}
230241
if !tt.wantErr && rsp.StatusCode != tt.want {
231242
t.Fatalf("Failed to get %d, got %d", tt.want, rsp.StatusCode)
232243
}
@@ -327,11 +338,14 @@ func TestProxyListenerWithBogusProxyClient(t *testing.T) {
327338

328339
client := createBogusProxyClient(addr, tt.destAddr, 8080, tt.version, tt.protocol)
329340

341+
shutdownCH := make(chan struct{})
330342
waitShutdownCH := make(chan struct{})
331343
go func() {
332-
time.Sleep(time.Second)
344+
<-shutdownCH
333345
t.Log("Start shutdown")
334-
if err := srv.Shutdown(context.Background()); err != nil {
346+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
347+
defer cancel()
348+
if err := srv.Shutdown(ctx); err != nil {
335349
t.Logf("Failed to graceful shutdown: %v", err)
336350
}
337351
close(waitShutdownCH)
@@ -352,9 +366,13 @@ func TestProxyListenerWithBogusProxyClient(t *testing.T) {
352366
}
353367
req.Host = tt.host
354368
rsp, err := client.Do(req)
369+
close(shutdownCH)
355370
if err != nil && !tt.wantErr {
356371
t.Fatalf("Failed to get response: %v", err)
357372
}
373+
if rsp != nil {
374+
rsp.Body.Close()
375+
}
358376
if !tt.wantErr && rsp.StatusCode != tt.want {
359377
t.Fatalf("Failed to get %d, got %d", tt.want, rsp.StatusCode)
360378
}
@@ -488,13 +506,20 @@ func TestProxyListenerWithHttpClient(t *testing.T) {
488506
}),
489507
}
490508

491-
client := http.DefaultClient
509+
// Use a per-subtest client with keep-alives disabled to prevent
510+
// idle connections from one subtest from contaminating the next.
511+
client := &http.Client{
512+
Transport: &http.Transport{DisableKeepAlives: true},
513+
}
492514

515+
shutdownCH := make(chan struct{})
493516
waitShutdownCH := make(chan struct{})
494517
go func() {
495-
time.Sleep(time.Second)
518+
<-shutdownCH
496519
t.Log("Start shutdown")
497-
if err := srv.Shutdown(context.Background()); err != nil {
520+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
521+
defer cancel()
522+
if err := srv.Shutdown(ctx); err != nil {
498523
t.Logf("Failed to graceful shutdown: %v", err)
499524
}
500525
close(waitShutdownCH)
@@ -515,9 +540,13 @@ func TestProxyListenerWithHttpClient(t *testing.T) {
515540
}
516541
req.Host = tt.host
517542
rsp, err := client.Do(req)
543+
close(shutdownCH)
518544
if err != nil && !tt.wantErr {
519545
t.Fatalf("Failed to get response: %v", err)
520546
}
547+
if rsp != nil {
548+
rsp.Body.Close()
549+
}
521550
if !tt.wantErr && rsp.StatusCode != tt.want {
522551
t.Fatalf("Failed to get %d, got %d", tt.want, rsp.StatusCode)
523552
}

0 commit comments

Comments
 (0)