github.com/moby/docker@v26.1.3+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.Check(t, is.ErrorContains(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.Check(t, is.ErrorContains(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 return nil, errors.New("some connection error") 57 }), 58 } 59 60 ping, err := client.Ping(context.Background()) 61 assert.Check(t, is.ErrorContains(err, "some connection error")) 62 assert.Check(t, is.Equal(false, ping.Experimental)) 63 assert.Check(t, is.Equal("", ping.APIVersion)) 64 var si *swarm.Status 65 assert.Check(t, is.Equal(si, ping.SwarmStatus)) 66 } 67 68 // TestPingSuccess tests that we are able to get the expected API headers/ping 69 // details on success. 70 func TestPingSuccess(t *testing.T) { 71 client := &Client{ 72 client: newMockClient(func(req *http.Request) (*http.Response, error) { 73 resp := &http.Response{StatusCode: http.StatusOK} 74 resp.Header = http.Header{} 75 resp.Header.Set("API-Version", "awesome") 76 resp.Header.Set("Docker-Experimental", "true") 77 resp.Header.Set("Swarm", "active/manager") 78 resp.Body = io.NopCloser(strings.NewReader("OK")) 79 return resp, nil 80 }), 81 } 82 ping, err := client.Ping(context.Background()) 83 assert.NilError(t, err) 84 assert.Check(t, is.Equal(true, ping.Experimental)) 85 assert.Check(t, is.Equal("awesome", ping.APIVersion)) 86 assert.Check(t, is.Equal(swarm.Status{NodeState: "active", ControlAvailable: true}, *ping.SwarmStatus)) 87 } 88 89 // TestPingHeadFallback tests that the client falls back to GET if HEAD fails. 90 func TestPingHeadFallback(t *testing.T) { 91 tests := []struct { 92 status int 93 expected string 94 }{ 95 { 96 status: http.StatusOK, 97 expected: http.MethodHead, 98 }, 99 { 100 status: http.StatusInternalServerError, 101 expected: http.MethodHead, 102 }, 103 { 104 status: http.StatusNotFound, 105 expected: "HEAD, GET", 106 }, 107 { 108 status: http.StatusMethodNotAllowed, 109 expected: "HEAD, GET", 110 }, 111 } 112 113 for _, tc := range tests { 114 tc := tc 115 t.Run(http.StatusText(tc.status), func(t *testing.T) { 116 var reqs []string 117 client := &Client{ 118 client: newMockClient(func(req *http.Request) (*http.Response, error) { 119 reqs = append(reqs, req.Method) 120 resp := &http.Response{StatusCode: http.StatusOK} 121 if req.Method == http.MethodHead { 122 resp.StatusCode = tc.status 123 } 124 resp.Header = http.Header{} 125 resp.Header.Add("API-Version", strings.Join(reqs, ", ")) 126 return resp, nil 127 }), 128 } 129 ping, _ := client.Ping(context.Background()) 130 assert.Check(t, is.Equal(ping.APIVersion, tc.expected)) 131 }) 132 } 133 }