| package client // import "github.com/docker/docker/client" | |
| import ( | |
| "context" | |
| "errors" | |
| "io" | |
| "net/http" | |
| "strings" | |
| "testing" | |
| "github.com/docker/docker/api/types/swarm" | |
| "gotest.tools/v3/assert" | |
| is "gotest.tools/v3/assert/cmp" | |
| ) | |
| // TestPingFail tests that when a server sends a non-successful response that we | |
| // can still grab API details, when set. | |
| // Some of this is just exercising the code paths to make sure there are no | |
| // panics. | |
| func TestPingFail(t *testing.T) { | |
| var withHeader bool | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| resp := &http.Response{StatusCode: http.StatusInternalServerError} | |
| if withHeader { | |
| resp.Header = http.Header{} | |
| resp.Header.Set("Api-Version", "awesome") | |
| resp.Header.Set("Docker-Experimental", "true") | |
| resp.Header.Set("Swarm", "inactive") | |
| } | |
| resp.Body = io.NopCloser(strings.NewReader("some error with the server")) | |
| return resp, nil | |
| }), | |
| } | |
| ping, err := client.Ping(context.Background()) | |
| assert.Check(t, is.ErrorContains(err, "some error with the server")) | |
| assert.Check(t, is.Equal(false, ping.Experimental)) | |
| assert.Check(t, is.Equal("", ping.APIVersion)) | |
| var si *swarm.Status | |
| assert.Check(t, is.Equal(si, ping.SwarmStatus)) | |
| withHeader = true | |
| ping2, err := client.Ping(context.Background()) | |
| assert.Check(t, is.ErrorContains(err, "some error with the server")) | |
| assert.Check(t, is.Equal(true, ping2.Experimental)) | |
| assert.Check(t, is.Equal("awesome", ping2.APIVersion)) | |
| assert.Check(t, is.Equal(swarm.Status{NodeState: "inactive"}, *ping2.SwarmStatus)) | |
| } | |
| // TestPingWithError tests the case where there is a protocol error in the ping. | |
| // This test is mostly just testing that there are no panics in this code path. | |
| func TestPingWithError(t *testing.T) { | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| return nil, errors.New("some connection error") | |
| }), | |
| } | |
| ping, err := client.Ping(context.Background()) | |
| assert.Check(t, is.ErrorContains(err, "some connection error")) | |
| assert.Check(t, is.Equal(false, ping.Experimental)) | |
| assert.Check(t, is.Equal("", ping.APIVersion)) | |
| var si *swarm.Status | |
| assert.Check(t, is.Equal(si, ping.SwarmStatus)) | |
| } | |
| // TestPingSuccess tests that we are able to get the expected API headers/ping | |
| // details on success. | |
| func TestPingSuccess(t *testing.T) { | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| resp := &http.Response{StatusCode: http.StatusOK} | |
| resp.Header = http.Header{} | |
| resp.Header.Set("Api-Version", "awesome") | |
| resp.Header.Set("Docker-Experimental", "true") | |
| resp.Header.Set("Swarm", "active/manager") | |
| resp.Body = io.NopCloser(strings.NewReader("OK")) | |
| return resp, nil | |
| }), | |
| } | |
| ping, err := client.Ping(context.Background()) | |
| assert.NilError(t, err) | |
| assert.Check(t, is.Equal(true, ping.Experimental)) | |
| assert.Check(t, is.Equal("awesome", ping.APIVersion)) | |
| assert.Check(t, is.Equal(swarm.Status{NodeState: "active", ControlAvailable: true}, *ping.SwarmStatus)) | |
| } | |
| // TestPingHeadFallback tests that the client falls back to GET if HEAD fails. | |
| func TestPingHeadFallback(t *testing.T) { | |
| tests := []struct { | |
| status int | |
| expected string | |
| }{ | |
| { | |
| status: http.StatusOK, | |
| expected: http.MethodHead, | |
| }, | |
| { | |
| status: http.StatusInternalServerError, | |
| expected: http.MethodHead, | |
| }, | |
| { | |
| status: http.StatusNotFound, | |
| expected: "HEAD, GET", | |
| }, | |
| { | |
| status: http.StatusMethodNotAllowed, | |
| expected: "HEAD, GET", | |
| }, | |
| } | |
| for _, tc := range tests { | |
| tc := tc | |
| t.Run(http.StatusText(tc.status), func(t *testing.T) { | |
| var reqs []string | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| reqs = append(reqs, req.Method) | |
| resp := &http.Response{StatusCode: http.StatusOK} | |
| if req.Method == http.MethodHead { | |
| resp.StatusCode = tc.status | |
| } | |
| resp.Header = http.Header{} | |
| resp.Header.Add("Api-Version", strings.Join(reqs, ", ")) | |
| return resp, nil | |
| }), | |
| } | |
| ping, _ := client.Ping(context.Background()) | |
| assert.Check(t, is.Equal(ping.APIVersion, tc.expected)) | |
| }) | |
| } | |
| } |