1 package opts
2
3 import (
4 "fmt"
5 "testing"
6
7 "gotest.tools/v3/assert"
8 is "gotest.tools/v3/assert/cmp"
9 )
10
11 func TestParseHost(t *testing.T) {
12 invalid := []string{
13 "something with spaces",
14 "://",
15 "unknown://",
16 "tcp://:port",
17 "tcp://invalid:port",
18 }
19
20 valid := map[string]string{
21 "": defaultHost,
22 " ": defaultHost,
23 " ": defaultHost,
24 "fd://": "fd://",
25 "fd://something": "fd://something",
26 "tcp://host:": fmt.Sprintf("tcp://host:%s", defaultHTTPPort),
27 "tcp://": defaultTCPHost,
28 "tcp://:2375": fmt.Sprintf("tcp://%s:%s", defaultHTTPHost, defaultHTTPPort),
29 "tcp://:2376": fmt.Sprintf("tcp://%s:%s", defaultHTTPHost, defaultTLSHTTPPort),
30 "tcp://0.0.0.0:8080": "tcp://0.0.0.0:8080",
31 "tcp://192.168.0.0:12000": "tcp://192.168.0.0:12000",
32 "tcp://192.168:8080": "tcp://192.168:8080",
33 "tcp://0.0.0.0:1234567890": "tcp://0.0.0.0:1234567890",
34 " tcp://:7777/path ": fmt.Sprintf("tcp://%s:7777/path", defaultHTTPHost),
35 "tcp://docker.com:2375": "tcp://docker.com:2375",
36 "unix://": "unix://" + defaultUnixSocket,
37 "unix://path/to/socket": "unix://path/to/socket",
38 "npipe://": "npipe://" + defaultNamedPipe,
39 "npipe:////./pipe/foo": "npipe:////./pipe/foo",
40 }
41
42 for _, value := range invalid {
43 if _, err := ParseHost(false, value); err == nil {
44 t.Errorf("Expected an error for %v, got [nil]", value)
45 }
46 }
47
48 for value, expected := range valid {
49 if actual, err := ParseHost(false, value); err != nil || actual != expected {
50 t.Errorf("Expected for %v [%v], got [%v, %v]", value, expected, actual, err)
51 }
52 }
53 }
54
55 func TestParseDockerDaemonHost(t *testing.T) {
56 invalids := map[string]string{
57 "tcp:a.b.c.d": "",
58 "tcp:a.b.c.d/path": "",
59 "udp://127.0.0.1": "invalid bind address format: udp://127.0.0.1",
60 "udp://127.0.0.1:2375": "invalid bind address format: udp://127.0.0.1:2375",
61 "tcp://unix:///run/docker.sock": "invalid proto, expected tcp: unix:///run/docker.sock",
62 " tcp://:7777/path ": "invalid bind address format: tcp://:7777/path ",
63 "": "invalid bind address format: ",
64 }
65 valids := map[string]string{
66 "0.0.0.1:": "tcp://0.0.0.1:2375",
67 "0.0.0.1:5555": "tcp://0.0.0.1:5555",
68 "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path",
69 "[::1]:": "tcp://[::1]:2375",
70 "[::1]:5555/path": "tcp://[::1]:5555/path",
71 "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2375",
72 "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
73 ":6666": fmt.Sprintf("tcp://%s:6666", defaultHTTPHost),
74 ":6666/path": fmt.Sprintf("tcp://%s:6666/path", defaultHTTPHost),
75 "tcp://": defaultTCPHost,
76 "tcp://:7777": fmt.Sprintf("tcp://%s:7777", defaultHTTPHost),
77 "tcp://:7777/path": fmt.Sprintf("tcp://%s:7777/path", defaultHTTPHost),
78 "unix:///run/docker.sock": "unix:///run/docker.sock",
79 "unix://": "unix://" + defaultUnixSocket,
80 "fd://": "fd://",
81 "fd://something": "fd://something",
82 "localhost:": "tcp://localhost:2375",
83 "localhost:5555": "tcp://localhost:5555",
84 "localhost:5555/path": "tcp://localhost:5555/path",
85 }
86 for invalidAddr, expectedError := range invalids {
87 if addr, err := parseDockerDaemonHost(invalidAddr); err == nil || expectedError != "" && err.Error() != expectedError {
88 t.Errorf("tcp %v address expected error %q return, got %q and addr %v", invalidAddr, expectedError, err, addr)
89 }
90 }
91 for validAddr, expectedAddr := range valids {
92 if addr, err := parseDockerDaemonHost(validAddr); err != nil || addr != expectedAddr {
93 t.Errorf("%v -> expected %v, got (%v) addr (%v)", validAddr, expectedAddr, err, addr)
94 }
95 }
96 }
97
98 func TestParseTCP(t *testing.T) {
99 defaultHTTPHost := "tcp://127.0.0.1:2376"
100 invalids := map[string]string{
101 "tcp:a.b.c.d": "",
102 "tcp:a.b.c.d/path": "",
103 "udp://127.0.0.1": "invalid proto, expected tcp: udp://127.0.0.1",
104 "udp://127.0.0.1:2375": "invalid proto, expected tcp: udp://127.0.0.1:2375",
105 }
106 valids := map[string]string{
107 "": defaultHTTPHost,
108 "tcp://": defaultHTTPHost,
109 "0.0.0.1:": "tcp://0.0.0.1:2376",
110 "0.0.0.1:5555": "tcp://0.0.0.1:5555",
111 "0.0.0.1:5555/path": "tcp://0.0.0.1:5555/path",
112 ":6666": "tcp://127.0.0.1:6666",
113 ":6666/path": "tcp://127.0.0.1:6666/path",
114 "tcp://:7777": "tcp://127.0.0.1:7777",
115 "tcp://:7777/path": "tcp://127.0.0.1:7777/path",
116 "[::1]:": "tcp://[::1]:2376",
117 "[::1]:5555": "tcp://[::1]:5555",
118 "[::1]:5555/path": "tcp://[::1]:5555/path",
119 "[0:0:0:0:0:0:0:1]:": "tcp://[0:0:0:0:0:0:0:1]:2376",
120 "[0:0:0:0:0:0:0:1]:5555": "tcp://[0:0:0:0:0:0:0:1]:5555",
121 "[0:0:0:0:0:0:0:1]:5555/path": "tcp://[0:0:0:0:0:0:0:1]:5555/path",
122 "localhost:": "tcp://localhost:2376",
123 "localhost:5555": "tcp://localhost:5555",
124 "localhost:5555/path": "tcp://localhost:5555/path",
125 }
126 for invalidAddr, expectedError := range invalids {
127 if addr, err := ParseTCPAddr(invalidAddr, defaultHTTPHost); err == nil || expectedError != "" && err.Error() != expectedError {
128 t.Errorf("tcp %v address expected error %v return, got %s and addr %v", invalidAddr, expectedError, err, addr)
129 }
130 }
131 for validAddr, expectedAddr := range valids {
132 if addr, err := ParseTCPAddr(validAddr, defaultHTTPHost); err != nil || addr != expectedAddr {
133 t.Errorf("%v -> expected %v, got %v and addr %v", validAddr, expectedAddr, err, addr)
134 }
135 }
136 }
137
138 func TestParseInvalidUnixAddrInvalid(t *testing.T) {
139 if _, err := parseSimpleProtoAddr("unix", "tcp://127.0.0.1", "unix:///var/run/docker.sock"); err == nil || err.Error() != "invalid proto, expected unix: tcp://127.0.0.1" {
140 t.Fatalf("Expected an error, got %v", err)
141 }
142 if _, err := parseSimpleProtoAddr("unix", "unix://tcp://127.0.0.1", "/var/run/docker.sock"); err == nil || err.Error() != "invalid proto, expected unix: tcp://127.0.0.1" {
143 t.Fatalf("Expected an error, got %v", err)
144 }
145 if v, err := parseSimpleProtoAddr("unix", "", "/var/run/docker.sock"); err != nil || v != "unix:///var/run/docker.sock" {
146 t.Fatalf("Expected an %v, got %v", v, "unix:///var/run/docker.sock")
147 }
148 }
149
150 func TestValidateExtraHosts(t *testing.T) {
151 tests := []struct {
152 doc string
153 input string
154 expectedOut string
155 expectedErr string
156 }{
157 {
158 doc: "IPv4, colon sep",
159 input: `myhost:192.168.0.1`,
160 },
161 {
162 doc: "IPv4, eq sep",
163 input: `myhost=192.168.0.1`,
164 expectedOut: `myhost:192.168.0.1`,
165 },
166 {
167 doc: "Weird but permitted, IPv4 with brackets",
168 input: `myhost=[192.168.0.1]`,
169 expectedOut: `myhost:192.168.0.1`,
170 },
171 {
172 doc: "Host and domain",
173 input: `host.and.domain.invalid:10.0.2.1`,
174 },
175 {
176 doc: "IPv6, colon sep",
177 input: `anipv6host:2003:ab34:e::1`,
178 },
179 {
180 doc: "IPv6, colon sep, brackets",
181 input: `anipv6host:[2003:ab34:e::1]`,
182 expectedOut: `anipv6host:2003:ab34:e::1`,
183 },
184 {
185 doc: "IPv6, eq sep, brackets",
186 input: `anipv6host=[2003:ab34:e::1]`,
187 expectedOut: `anipv6host:2003:ab34:e::1`,
188 },
189 {
190 doc: "IPv6 localhost, colon sep",
191 input: `ipv6local:::1`,
192 },
193 {
194 doc: "IPv6 localhost, eq sep",
195 input: `ipv6local=::1`,
196 expectedOut: `ipv6local:::1`,
197 },
198 {
199 doc: "IPv6 localhost, eq sep, brackets",
200 input: `ipv6local=[::1]`,
201 expectedOut: `ipv6local:::1`,
202 },
203 {
204 doc: "IPv6 localhost, non-canonical, colon sep",
205 input: `ipv6local:0:0:0:0:0:0:0:1`,
206 },
207 {
208 doc: "IPv6 localhost, non-canonical, eq sep",
209 input: `ipv6local=0:0:0:0:0:0:0:1`,
210 expectedOut: `ipv6local:0:0:0:0:0:0:0:1`,
211 },
212 {
213 doc: "IPv6 localhost, non-canonical, eq sep, brackets",
214 input: `ipv6local=[0:0:0:0:0:0:0:1]`,
215 expectedOut: `ipv6local:0:0:0:0:0:0:0:1`,
216 },
217 {
218 doc: "host-gateway special case, colon sep",
219 input: `host.docker.internal:host-gateway`,
220 },
221 {
222 doc: "host-gateway special case, eq sep",
223 input: `host.docker.internal=host-gateway`,
224 expectedOut: `host.docker.internal:host-gateway`,
225 },
226 {
227 doc: "Bad address, colon sep",
228 input: `myhost:192.notanipaddress.1`,
229 expectedErr: `invalid IP address in add-host: "192.notanipaddress.1"`,
230 },
231 {
232 doc: "Bad address, eq sep",
233 input: `myhost=192.notanipaddress.1`,
234 expectedErr: `invalid IP address in add-host: "192.notanipaddress.1"`,
235 },
236 {
237 doc: "No sep",
238 input: `thathost-nosemicolon10.0.0.1`,
239 expectedErr: `bad format for add-host: "thathost-nosemicolon10.0.0.1"`,
240 },
241 {
242 doc: "Bad IPv6",
243 input: `anipv6host:::::1`,
244 expectedErr: `invalid IP address in add-host: "::::1"`,
245 },
246 {
247 doc: "Bad IPv6, trailing colons",
248 input: `ipv6local:::0::`,
249 expectedErr: `invalid IP address in add-host: "::0::"`,
250 },
251 {
252 doc: "Bad IPv6, missing close bracket",
253 input: `ipv6addr=[::1`,
254 expectedErr: `invalid IP address in add-host: "[::1"`,
255 },
256 {
257 doc: "Bad IPv6, missing open bracket",
258 input: `ipv6addr=::1]`,
259 expectedErr: `invalid IP address in add-host: "::1]"`,
260 },
261 {
262 doc: "Missing address, colon sep",
263 input: `myhost.invalid:`,
264 expectedErr: `invalid IP address in add-host: ""`,
265 },
266 {
267 doc: "Missing address, eq sep",
268 input: `myhost.invalid=`,
269 expectedErr: `invalid IP address in add-host: ""`,
270 },
271 {
272 doc: "IPv6 localhost, bad name",
273 input: `:=::1`,
274 expectedErr: `bad format for add-host: ":=::1"`,
275 },
276 {
277 doc: "No input",
278 input: ``,
279 expectedErr: `bad format for add-host: ""`,
280 },
281 }
282
283 for _, tc := range tests {
284 tc := tc
285 if tc.expectedOut == "" {
286 tc.expectedOut = tc.input
287 }
288 t.Run(tc.input, func(t *testing.T) {
289 actualOut, actualErr := ValidateExtraHost(tc.input)
290 if tc.expectedErr == "" {
291 assert.Check(t, is.Equal(tc.expectedOut, actualOut))
292 assert.NilError(t, actualErr)
293 } else {
294 assert.Check(t, actualOut == "")
295 assert.Check(t, is.Error(actualErr, tc.expectedErr))
296 }
297 })
298 }
299 }
300
View as plain text