github.com/rumpl/bof@v23.0.0-rc.2+incompatible/client/ping_test.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "context" 5 "errors" 6 "io" 7 "net/http" 8 "strings" 9 "testing" 10 11 "github.com/docker/docker/api/types/swarm" 12 "gotest.tools/v3/assert" 13 is "gotest.tools/v3/assert/cmp" 14 ) 15 16 // TestPingFail tests that when a server sends a non-successful response that we 17 // can still grab API details, when set. 18 // Some of this is just exercising the code paths to make sure there are no 19 // panics. 20 func TestPingFail(t *testing.T) { 21 var withHeader bool 22 client := &Client{ 23 client: newMockClient(func(req *http.Request) (*http.Response, error) { 24 resp := &http.Response{StatusCode: http.StatusInternalServerError} 25 if withHeader { 26 resp.Header = http.Header{} 27 resp.Header.Set("API-Version", "awesome") 28 resp.Header.Set("Docker-Experimental", "true") 29 resp.Header.Set("Swarm", "inactive") 30 } 31 resp.Body = io.NopCloser(strings.NewReader("some error with the server")) 32 return resp, nil 33 }), 34 } 35 36 ping, err := client.Ping(context.Background()) 37 assert.ErrorContains(t, err, "some error with the server") 38 assert.Check(t, is.Equal(false, ping.Experimental)) 39 assert.Check(t, is.Equal("", ping.APIVersion)) 40 var si *swarm.Status 41 assert.Check(t, is.Equal(si, ping.SwarmStatus)) 42 43 withHeader = true 44 ping2, err := client.Ping(context.Background()) 45 assert.ErrorContains(t, err, "some error with the server") 46 assert.Check(t, is.Equal(true, ping2.Experimental)) 47 assert.Check(t, is.Equal("awesome", ping2.APIVersion)) 48 assert.Check(t, is.Equal(swarm.Status{NodeState: "inactive"}, *ping2.SwarmStatus)) 49 } 50 51 // TestPingWithError tests the case where there is a protocol error in the ping. 52 // This test is mostly just testing that there are no panics in this code path. 53 func TestPingWithError(t *testing.T) { 54 client := &Client{ 55 client: newMockClient(func(req *http.Request) (*http.Response, error) { 56 resp := &http.Response{StatusCode: http.StatusInternalServerError} 57 resp.Header = http.Header{} 58 resp.Header.Set("API-Version", "awesome") 59 resp.Header.Set("Docker-Experimental", "true") 60 resp.Header.Set("Swarm", "active/manager") 61 resp.Body = io.NopCloser(strings.NewReader("some error with the server")) 62 return resp, errors.New("some error") 63 }), 64 } 65 66 ping, err := client.Ping(context.Background()) 67 assert.ErrorContains(t, err, "some error") 68 assert.Check(t, is.Equal(false, ping.Experimental)) 69 assert.Check(t, is.Equal("", ping.APIVersion)) 70 var si *swarm.Status 71 assert.Check(t, is.Equal(si, ping.SwarmStatus)) 72 } 73 74 // TestPingSuccess tests that we are able to get the expected API headers/ping 75 // details on success. 76 func TestPingSuccess(t *testing.T) { 77 client := &Client{ 78 client: newMockClient(func(req *http.Request) (*http.Response, error) { 79 resp := &http.Response{StatusCode: http.StatusOK} 80 resp.Header = http.Header{} 81 resp.Header.Set("API-Version", "awesome") 82 resp.Header.Set("Docker-Experimental", "true") 83 resp.Header.Set("Swarm", "active/manager") 84 resp.Body = io.NopCloser(strings.NewReader("OK")) 85 return resp, nil 86 }), 87 } 88 ping, err := client.Ping(context.Background()) 89 assert.NilError(t, err) 90 assert.Check(t, is.Equal(true, ping.Experimental)) 91 assert.Check(t, is.Equal("awesome", ping.APIVersion)) 92 assert.Check(t, is.Equal(swarm.Status{NodeState: "active", ControlAvailable: true}, *ping.SwarmStatus)) 93 } 94 95 // TestPingHeadFallback tests that the client falls back to GET if HEAD fails. 96 func TestPingHeadFallback(t *testing.T) { 97 tests := []struct { 98 status int 99 expected string 100 }{ 101 { 102 status: http.StatusOK, 103 expected: http.MethodHead, 104 }, 105 { 106 status: http.StatusInternalServerError, 107 expected: http.MethodHead, 108 }, 109 { 110 status: http.StatusNotFound, 111 expected: "HEAD, GET", 112 }, 113 { 114 status: http.StatusMethodNotAllowed, 115 expected: "HEAD, GET", 116 }, 117 } 118 119 for _, tc := range tests { 120 tc := tc 121 t.Run(http.StatusText(tc.status), func(t *testing.T) { 122 var reqs []string 123 client := &Client{ 124 client: newMockClient(func(req *http.Request) (*http.Response, error) { 125 reqs = append(reqs, req.Method) 126 resp := &http.Response{StatusCode: http.StatusOK} 127 if req.Method == http.MethodHead { 128 resp.StatusCode = tc.status 129 } 130 resp.Header = http.Header{} 131 resp.Header.Add("API-Version", strings.Join(reqs, ", ")) 132 return resp, nil 133 }), 134 } 135 ping, _ := client.Ping(context.Background()) 136 assert.Check(t, is.Equal(ping.APIVersion, tc.expected)) 137 }) 138 } 139 }