1package client // import "github.com/docker/docker/client"
2
3import (
4	"bytes"
5	"context"
6	"fmt"
7	"io/ioutil"
8	"math/rand"
9	"net/http"
10	"strings"
11	"testing"
12
13	"github.com/docker/docker/api/types"
14	"github.com/docker/docker/errdefs"
15	"gotest.tools/v3/assert"
16	is "gotest.tools/v3/assert/cmp"
17)
18
19// TestSetHostHeader should set fake host for local communications, set real host
20// for normal communications.
21func TestSetHostHeader(t *testing.T) {
22	testURL := "/test"
23	testCases := []struct {
24		host            string
25		expectedHost    string
26		expectedURLHost string
27	}{
28		{
29			"unix:///var/run/docker.sock",
30			"docker",
31			"/var/run/docker.sock",
32		},
33		{
34			"npipe:////./pipe/docker_engine",
35			"docker",
36			"//./pipe/docker_engine",
37		},
38		{
39			"tcp://0.0.0.0:4243",
40			"",
41			"0.0.0.0:4243",
42		},
43		{
44			"tcp://localhost:4243",
45			"",
46			"localhost:4243",
47		},
48	}
49
50	for c, test := range testCases {
51		hostURL, err := ParseHostURL(test.host)
52		assert.NilError(t, err)
53
54		client := &Client{
55			client: newMockClient(func(req *http.Request) (*http.Response, error) {
56				if !strings.HasPrefix(req.URL.Path, testURL) {
57					return nil, fmt.Errorf("Test Case #%d: Expected URL %q, got %q", c, testURL, req.URL)
58				}
59				if req.Host != test.expectedHost {
60					return nil, fmt.Errorf("Test Case #%d: Expected host %q, got %q", c, test.expectedHost, req.Host)
61				}
62				if req.URL.Host != test.expectedURLHost {
63					return nil, fmt.Errorf("Test Case #%d: Expected URL host %q, got %q", c, test.expectedURLHost, req.URL.Host)
64				}
65				return &http.Response{
66					StatusCode: http.StatusOK,
67					Body:       ioutil.NopCloser(bytes.NewReader([]byte(""))),
68				}, nil
69			}),
70
71			proto:    hostURL.Scheme,
72			addr:     hostURL.Host,
73			basePath: hostURL.Path,
74		}
75
76		_, err = client.sendRequest(context.Background(), http.MethodGet, testURL, nil, nil, nil)
77		assert.NilError(t, err)
78	}
79}
80
81// TestPlainTextError tests the server returning an error in plain text for
82// backwards compatibility with API versions <1.24. All other tests use
83// errors returned as JSON
84func TestPlainTextError(t *testing.T) {
85	client := &Client{
86		client: newMockClient(plainTextErrorMock(http.StatusInternalServerError, "Server error")),
87	}
88	_, err := client.ContainerList(context.Background(), types.ContainerListOptions{})
89	if !errdefs.IsSystem(err) {
90		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
91	}
92}
93
94func TestInfiniteError(t *testing.T) {
95	infinitR := rand.New(rand.NewSource(42))
96	client := &Client{
97		client: newMockClient(func(req *http.Request) (*http.Response, error) {
98			resp := &http.Response{StatusCode: http.StatusInternalServerError}
99			resp.Header = http.Header{}
100			resp.Body = ioutil.NopCloser(infinitR)
101			return resp, nil
102		}),
103	}
104
105	_, err := client.Ping(context.Background())
106	assert.Check(t, is.ErrorContains(err, "request returned Internal Server Error"))
107}
108