1package url
2
3import (
4	"testing"
5)
6
7type formatTestCase struct {
8	url               *URL
9	environmentPrefix string
10	expected          string
11}
12
13func (c *formatTestCase) run(t *testing.T) {
14	formatted := c.url.Format(c.environmentPrefix)
15	if formatted != c.expected {
16		t.Fatal("formatting mismatch:", formatted, "!=", c.expected)
17	}
18}
19
20func TestFormatInvalidProtocol(t *testing.T) {
21	defer func() {
22		if r := recover(); r == nil {
23			t.Error("formatting invalid protocol did not panic")
24		}
25	}()
26	url := &URL{Protocol: Protocol(-1)}
27	url.Format("")
28}
29
30func TestFormatLocal(t *testing.T) {
31	test := &formatTestCase{
32		url: &URL{
33			Protocol: Protocol_Local,
34			Path:     "/test/path",
35		},
36		expected: "/test/path",
37	}
38	test.run(t)
39}
40
41func TestFormatForwardingLocal(t *testing.T) {
42	test := &formatTestCase{
43		url: &URL{
44			Kind:     Kind_Forwarding,
45			Protocol: Protocol_Local,
46			Path:     "/test/path",
47		},
48		expected: "/test/path",
49	}
50	test.run(t)
51}
52
53func TestFormatSSHHostnamePath(t *testing.T) {
54	test := &formatTestCase{
55		url: &URL{
56			Protocol: Protocol_SSH,
57			User:     "",
58			Host:     "host",
59			Port:     0,
60			Path:     "/test/path",
61		},
62		expected: "host:/test/path",
63	}
64	test.run(t)
65}
66
67func TestFormatForwardingSSHHostnamePath(t *testing.T) {
68	test := &formatTestCase{
69		url: &URL{
70			Protocol: Protocol_SSH,
71			User:     "",
72			Host:     "host",
73			Port:     0,
74			Path:     "tcp:localhost:6060",
75		},
76		expected: "host:tcp:localhost:6060",
77	}
78	test.run(t)
79}
80
81func TestFormatSSHUsernameHostnamePath(t *testing.T) {
82	test := &formatTestCase{
83		url: &URL{
84			Protocol: Protocol_SSH,
85			User:     "user",
86			Host:     "host",
87			Port:     0,
88			Path:     "/test/path",
89		},
90		expected: "user@host:/test/path",
91	}
92	test.run(t)
93}
94
95func TestFormatSSHHostnamePortPath(t *testing.T) {
96	test := &formatTestCase{
97		url: &URL{
98			Protocol: Protocol_SSH,
99			User:     "",
100			Host:     "host",
101			Port:     23,
102			Path:     "/test/path",
103		},
104		expected: "host:23:/test/path",
105	}
106	test.run(t)
107}
108
109func TestFormatSSHUsernameHostnamePortPath(t *testing.T) {
110	test := &formatTestCase{
111		url: &URL{
112			Protocol: Protocol_SSH,
113			User:     "user",
114			Host:     "host",
115			Port:     23,
116			Path:     "/test/path",
117		},
118		expected: "user@host:23:/test/path",
119	}
120	test.run(t)
121}
122
123func TestFormatTunnelInvalidUsername(t *testing.T) {
124	test := &formatTestCase{
125		url: &URL{
126			Protocol: Protocol_Tunnel,
127			User:     "george",
128			Host:     "tunnelname",
129			Path:     "/test/path/to/the file",
130		},
131		expected: invalidTunnelURLFormat,
132	}
133	test.run(t)
134}
135
136func TestFormatTunnelInvalidEmptyPath(t *testing.T) {
137	test := &formatTestCase{
138		url: &URL{
139			Protocol: Protocol_Tunnel,
140			Host:     "tunnelname",
141			Path:     "",
142		},
143		expected: invalidTunnelURLFormat,
144	}
145	test.run(t)
146}
147
148func TestFormatTunnelInvalidBadFirstPathCharacter(t *testing.T) {
149	test := &formatTestCase{
150		url: &URL{
151			Protocol: Protocol_Tunnel,
152			Host:     "tunnelname",
153			Path:     "$5",
154		},
155		expected: invalidTunnelURLFormat,
156	}
157	test.run(t)
158}
159
160func TestFormatTunnel(t *testing.T) {
161	test := &formatTestCase{
162		url: &URL{
163			Protocol: Protocol_Tunnel,
164			Host:     "tunnelname",
165			Path:     "/test/path/to/the file",
166		},
167		expected: "tunnel://tunnelname/test/path/to/the file",
168	}
169	test.run(t)
170}
171
172func TestFormatForwardingTunnel(t *testing.T) {
173	test := &formatTestCase{
174		url: &URL{
175			Kind:     Kind_Forwarding,
176			Protocol: Protocol_Tunnel,
177			Host:     "tunnelname",
178			Path:     "tcp4:localhost:8080",
179		},
180		expected: "tunnel://tunnelname:tcp4:localhost:8080",
181	}
182	test.run(t)
183}
184
185func TestFormatTunnelWithHomeRelativePath(t *testing.T) {
186	test := &formatTestCase{
187		url: &URL{
188			Protocol: Protocol_Tunnel,
189			Host:     "tunnelname",
190			Path:     "~/test/path/to/the file",
191		},
192		expected: "tunnel://tunnelname/~/test/path/to/the file",
193	}
194	test.run(t)
195}
196
197func TestFormatTunnelWithUserRelativePath(t *testing.T) {
198	test := &formatTestCase{
199		url: &URL{
200			Protocol: Protocol_Tunnel,
201			Host:     "tunnelname",
202			Path:     "~otheruser/test/path/to/the file",
203		},
204		expected: "tunnel://tunnelname/~otheruser/test/path/to/the file",
205	}
206	test.run(t)
207}
208
209func TestFormatTunnelWithWindowsPathPath(t *testing.T) {
210	test := &formatTestCase{
211		url: &URL{
212			Protocol: Protocol_Tunnel,
213			Host:     "tunnelname",
214			Path:     `C:\A\Windows\File Path `,
215		},
216		expected: `tunnel://tunnelname/C:\A\Windows\File Path `,
217	}
218	test.run(t)
219}
220
221func TestFormatDockerInvalidEmptyPath(t *testing.T) {
222	test := &formatTestCase{
223		url: &URL{
224			Protocol: Protocol_Docker,
225			Host:     "container",
226			Path:     "",
227		},
228		expected: invalidDockerURLFormat,
229	}
230	test.run(t)
231}
232
233func TestFormatDockerInvalidBadFirstPathCharacter(t *testing.T) {
234	test := &formatTestCase{
235		url: &URL{
236			Protocol: Protocol_Docker,
237			Host:     "container",
238			Path:     "$5",
239		},
240		expected: invalidDockerURLFormat,
241	}
242	test.run(t)
243}
244
245func TestFormatDocker(t *testing.T) {
246	test := &formatTestCase{
247		url: &URL{
248			Protocol: Protocol_Docker,
249			Host:     "container",
250			Path:     "/test/path/to/the file",
251			Environment: map[string]string{
252				DockerHostEnvironmentVariable: "unix:///path/to/docker.sock",
253			},
254		},
255		environmentPrefix: "|",
256		expected:          "docker://container/test/path/to/the file|DOCKER_HOST=unix:///path/to/docker.sock|DOCKER_TLS_VERIFY=|DOCKER_CERT_PATH=|DOCKER_API_VERSION=",
257	}
258	test.run(t)
259}
260
261func TestFormatForwardingDocker(t *testing.T) {
262	test := &formatTestCase{
263		url: &URL{
264			Kind:     Kind_Forwarding,
265			Protocol: Protocol_Docker,
266			Host:     "container",
267			Path:     "tcp4:localhost:8080",
268			Environment: map[string]string{
269				DockerHostEnvironmentVariable: "unix:///path/to/docker.sock",
270			},
271		},
272		environmentPrefix: "|",
273		expected:          "docker://container:tcp4:localhost:8080|DOCKER_HOST=unix:///path/to/docker.sock|DOCKER_TLS_VERIFY=|DOCKER_CERT_PATH=|DOCKER_API_VERSION=",
274	}
275	test.run(t)
276}
277
278func TestFormatDockerWithUsernameAndHomeRelativePath(t *testing.T) {
279	test := &formatTestCase{
280		url: &URL{
281			Protocol: Protocol_Docker,
282			User:     "user",
283			Host:     "container",
284			Path:     "~/test/path/to/the file",
285			Environment: map[string]string{
286				DockerHostEnvironmentVariable:      "unix:///path/to/docker.sock",
287				DockerTLSVerifyEnvironmentVariable: "true",
288			},
289		},
290		environmentPrefix: "|",
291		expected:          "docker://user@container/~/test/path/to/the file|DOCKER_HOST=unix:///path/to/docker.sock|DOCKER_TLS_VERIFY=true|DOCKER_CERT_PATH=|DOCKER_API_VERSION=",
292	}
293	test.run(t)
294}
295
296func TestFormatDockerWithUsernameAndUserRelativePath(t *testing.T) {
297	test := &formatTestCase{
298		url: &URL{
299			Protocol: Protocol_Docker,
300			User:     "user",
301			Host:     "container",
302			Path:     "~otheruser/test/path/to/the file",
303			Environment: map[string]string{
304				DockerHostEnvironmentVariable:      "unix:///path/to/docker.sock",
305				DockerTLSVerifyEnvironmentVariable: "true",
306			},
307		},
308		environmentPrefix: "|",
309		expected:          "docker://user@container/~otheruser/test/path/to/the file|DOCKER_HOST=unix:///path/to/docker.sock|DOCKER_TLS_VERIFY=true|DOCKER_CERT_PATH=|DOCKER_API_VERSION=",
310	}
311	test.run(t)
312}
313
314func TestFormatDockerWithWindowsPathPath(t *testing.T) {
315	test := &formatTestCase{
316		url: &URL{
317			Protocol: Protocol_Docker,
318			Host:     "container",
319			Path:     `C:\A\Windows\File Path `,
320			Environment: map[string]string{
321				DockerHostEnvironmentVariable:      "unix:///path/to/docker.sock",
322				DockerTLSVerifyEnvironmentVariable: "true",
323			},
324		},
325		environmentPrefix: "|",
326		expected:          `docker://container/C:\A\Windows\File Path |DOCKER_HOST=unix:///path/to/docker.sock|DOCKER_TLS_VERIFY=true|DOCKER_CERT_PATH=|DOCKER_API_VERSION=`,
327	}
328	test.run(t)
329}
330