@@ -3,8 +3,11 @@ package test
33import (
44 "context"
55 "crypto/tls"
6+ "errors"
67 "fmt"
8+ "io"
79 "net/http"
10+ "net/http/httptrace"
811 "sync"
912 "syscall"
1013 "time"
@@ -69,19 +72,51 @@ func (s *GatewayOpsTestSuite) TestGracefulShutdown() {
6972 },
7073 }
7174
75+ var requestsWritten int
76+ var responsesReceived int
77+ trace := & httptrace.ClientTrace {
78+ WroteRequest : func (info httptrace.WroteRequestInfo ) {
79+ requestsWritten ++
80+ },
81+ GotFirstResponseByte : func () {
82+ responsesReceived ++
83+ },
84+ }
85+
86+ ctx := httptrace .WithClientTrace (context .Background (), trace )
87+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , fmt .Sprintf ("https://%s/v1/callerIdentity" , dapiAddr ), nil )
88+ assert .NoError (s .T (), err )
89+
7290 respCloseChan := make (chan (bool ), 10000 )
7391 var wg sync.WaitGroup
7492
93+ var eofs int
94+ var unexpectedErr error
7595 wg .Add (1 )
7696 go func () {
7797 defer wg .Done ()
7898
7999 for {
80- resp , err := dapiCli .Get ( fmt . Sprintf ( "https://%s/v1/callerIdentity" , dapiAddr ) )
100+ resp , err := dapiCli .Do ( req )
81101 if err != nil {
82- // A non-nil error should be caused by sending requests to the gateway
83- // after it has already shutdown.
84- assert .ErrorIs (s .T (), err , syscall .ECONNREFUSED )
102+ switch {
103+ case errors .Is (err , io .EOF ):
104+ // There is a small window between the flushing the request bytes to the socket and the http handler receiving
105+ // the bytes where the server sees the connection as idle and will close it. We record these errors and
106+ // include them when checking all requests recieved responses.
107+ eofs ++
108+ case errors .Is (err , syscall .ECONNREFUSED ):
109+ // This is what we expect to see once the listeners have closed
110+ case errors .Is (err , syscall .ECONNRESET ), errors .Is (err , syscall .EPIPE ):
111+ // Connection reset and broken pipe errors occur before the request is completely written, therefore the
112+ // wroteRequest hook has not triggered. Such racy errors are unavoidable when running directly against an
113+ // http server.
114+ default :
115+ // Any errors not mentinoned above are not expected and should cause a failure to be investigated.
116+ unexpectedErr = err
117+ return
118+ }
119+
85120 return
86121 }
87122
@@ -97,6 +132,9 @@ func (s *GatewayOpsTestSuite) TestGracefulShutdown() {
97132
98133 wg .Wait ()
99134
135+ assert .NoError (s .T (), unexpectedErr )
136+ assert .Equal (s .T (), requestsWritten , responsesReceived + eofs )
137+
100138 isFirstResponse := true
101139 keepAlivesDisabled := false
102140 for len (respCloseChan ) > 0 {
0 commit comments