@@ -16,6 +16,7 @@ package healthcheck_test
1616
1717import (
1818 "context"
19+ "errors"
1920 "fmt"
2021 "io"
2122 "net"
@@ -56,9 +57,14 @@ func dialTCP(t *testing.T, addr string) net.Conn {
5657 return nil
5758}
5859
59- type fakeDialer struct {}
60+ type fakeDialer struct {
61+ isClosed bool
62+ }
6063
61- func (* fakeDialer ) Dial (_ context.Context , _ string , _ ... cloudsqlconn.DialOption ) (net.Conn , error ) {
64+ func (f * fakeDialer ) Dial (_ context.Context , _ string , _ ... cloudsqlconn.DialOption ) (net.Conn , error ) {
65+ if f .isClosed {
66+ return nil , errors .New ("closed" )
67+ }
6268 conn , _ := net .Pipe ()
6369 return conn , nil
6470}
@@ -67,7 +73,11 @@ func (*fakeDialer) EngineVersion(_ context.Context, _ string) (string, error) {
6773 return "POSTGRES_14" , nil
6874}
6975
70- func (* fakeDialer ) Close () error {
76+ func (f * fakeDialer ) Close () error {
77+ if f .isClosed {
78+ return errors .New ("closed" )
79+ }
80+ f .isClosed = true
7181 return nil
7282}
7383
@@ -222,3 +232,56 @@ func TestHandleReadinessForMaxConns(t *testing.T) {
222232 t .Fatalf ("want max connections error, got = %v" , string (body ))
223233 }
224234}
235+ func TestHandleReadinessForMinReady (t * testing.T ) {
236+ p := newTestProxy (t )
237+ defer func () {
238+ p .Close ()
239+ }()
240+ started := make (chan struct {})
241+ check := healthcheck .NewCheck (p , logger )
242+ go p .Serve (context .Background (), func () {
243+ check .NotifyStarted ()
244+ close (started )
245+ })
246+ select {
247+ case <- started :
248+ // proxy has started
249+ case <- time .After (10 * time .Second ):
250+ t .Fatal ("proxy has not started after 10 seconds" )
251+ }
252+
253+ conn := dialTCP (t , proxyAddr ())
254+ defer conn .Close ()
255+
256+ minReadyTest := func (t * testing.T , minReady int , wantCode int ) * http.Response {
257+ rec := httptest .NewRecorder ()
258+ check .HandleReadiness (rec , & http.Request {URL : & url.URL {RawQuery : fmt .Sprintf ("min-ready=%d" , minReady )}})
259+ resp := rec .Result ()
260+ if resp .StatusCode == wantCode {
261+ return resp
262+ }
263+ t .Fatalf ("failed to receive status code = %v: %v" , wantCode , resp .StatusCode )
264+ return nil
265+ }
266+
267+ var resp * http.Response
268+
269+ resp = minReadyTest (t , 0 , http .StatusOK )
270+ resp = minReadyTest (t , 1 , http .StatusOK )
271+ resp = minReadyTest (t , 2 , http .StatusBadRequest )
272+
273+ conn .Close ()
274+ if err := p .Close (); err != nil {
275+ t .Logf ("failed to close proxy client: %v" , err )
276+ }
277+
278+ resp = minReadyTest (t , 1 , http .StatusServiceUnavailable )
279+
280+ body , err := io .ReadAll (resp .Body )
281+ if err != nil {
282+ t .Fatalf ("failed to read response body: %v" , err )
283+ }
284+ if ! strings .Contains (string (body ), "min ready" ) {
285+ t .Fatalf ("want max connections error, got = %v" , string (body ))
286+ }
287+ }
0 commit comments