| package client // import "github.com/docker/docker/client" | |
| import ( | |
| "bytes" | |
| "context" | |
| "errors" | |
| "fmt" | |
| "io" | |
| "math/rand" | |
| "net/http" | |
| "strings" | |
| "testing" | |
| "time" | |
| "github.com/docker/docker/api/types/container" | |
| "github.com/docker/docker/errdefs" | |
| "gotest.tools/v3/assert" | |
| is "gotest.tools/v3/assert/cmp" | |
| ) | |
| // TestSetHostHeader should set fake host for local communications, set real host | |
| // for normal communications. | |
| func TestSetHostHeader(t *testing.T) { | |
| const testEndpoint = "/test" | |
| testCases := []struct { | |
| host string | |
| expectedHost string | |
| expectedURLHost string | |
| }{ | |
| { | |
| host: "unix:///var/run/docker.sock", | |
| expectedHost: DummyHost, | |
| expectedURLHost: "/var/run/docker.sock", | |
| }, | |
| { | |
| host: "npipe:////./pipe/docker_engine", | |
| expectedHost: DummyHost, | |
| expectedURLHost: "//./pipe/docker_engine", | |
| }, | |
| { | |
| host: "tcp://0.0.0.0:4243", | |
| expectedHost: "", | |
| expectedURLHost: "0.0.0.0:4243", | |
| }, | |
| { | |
| host: "tcp://localhost:4243", | |
| expectedHost: "", | |
| expectedURLHost: "localhost:4243", | |
| }, | |
| } | |
| for _, tc := range testCases { | |
| tc := tc | |
| t.Run(tc.host, func(t *testing.T) { | |
| hostURL, err := ParseHostURL(tc.host) | |
| assert.Check(t, err) | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| if !strings.HasPrefix(req.URL.Path, testEndpoint) { | |
| return nil, fmt.Errorf("expected URL %q, got %q", testEndpoint, req.URL) | |
| } | |
| if req.Host != tc.expectedHost { | |
| return nil, fmt.Errorf("wxpected host %q, got %q", tc.expectedHost, req.Host) | |
| } | |
| if req.URL.Host != tc.expectedURLHost { | |
| return nil, fmt.Errorf("expected URL host %q, got %q", tc.expectedURLHost, req.URL.Host) | |
| } | |
| return &http.Response{ | |
| StatusCode: http.StatusOK, | |
| Body: io.NopCloser(bytes.NewReader([]byte(""))), | |
| }, nil | |
| }), | |
| proto: hostURL.Scheme, | |
| addr: hostURL.Host, | |
| basePath: hostURL.Path, | |
| } | |
| _, err = client.sendRequest(context.Background(), http.MethodGet, testEndpoint, nil, nil, nil) | |
| assert.Check(t, err) | |
| }) | |
| } | |
| } | |
| // TestPlainTextError tests the server returning an error in plain text for | |
| // backwards compatibility with API versions <1.24. All other tests use | |
| // errors returned as JSON | |
| func TestPlainTextError(t *testing.T) { | |
| client := &Client{ | |
| client: newMockClient(plainTextErrorMock(http.StatusInternalServerError, "Server error")), | |
| } | |
| _, err := client.ContainerList(context.Background(), container.ListOptions{}) | |
| assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) | |
| } | |
| func TestInfiniteError(t *testing.T) { | |
| infinitR := rand.New(rand.NewSource(42)) | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| resp := &http.Response{ | |
| StatusCode: http.StatusInternalServerError, | |
| Header: http.Header{}, | |
| Body: io.NopCloser(infinitR), | |
| } | |
| return resp, nil | |
| }), | |
| } | |
| _, err := client.Ping(context.Background()) | |
| assert.Check(t, is.ErrorContains(err, "request returned Internal Server Error")) | |
| } | |
| func TestCanceledContext(t *testing.T) { | |
| const testEndpoint = "/test" | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| assert.Check(t, is.ErrorType(req.Context().Err(), context.Canceled)) | |
| return nil, context.Canceled | |
| }), | |
| } | |
| ctx, cancel := context.WithCancel(context.Background()) | |
| cancel() | |
| _, err := client.sendRequest(ctx, http.MethodGet, testEndpoint, nil, nil, nil) | |
| assert.Check(t, is.ErrorType(err, errdefs.IsCancelled)) | |
| assert.Check(t, errors.Is(err, context.Canceled)) | |
| } | |
| func TestDeadlineExceededContext(t *testing.T) { | |
| const testEndpoint = "/test" | |
| client := &Client{ | |
| client: newMockClient(func(req *http.Request) (*http.Response, error) { | |
| assert.Check(t, is.ErrorType(req.Context().Err(), context.DeadlineExceeded)) | |
| return nil, context.DeadlineExceeded | |
| }), | |
| } | |
| ctx, cancel := context.WithDeadline(context.Background(), time.Now()) | |
| defer cancel() | |
| <-ctx.Done() | |
| _, err := client.sendRequest(ctx, http.MethodGet, testEndpoint, nil, nil, nil) | |
| assert.Check(t, is.ErrorType(err, errdefs.IsDeadline)) | |
| assert.Check(t, errors.Is(err, context.DeadlineExceeded)) | |
| } |