1 package nat
2
3 import (
4 "reflect"
5 "testing"
6 )
7
8 func TestParsePort(t *testing.T) {
9 var (
10 p int
11 err error
12 )
13
14 p, err = ParsePort("1234")
15
16 if err != nil || p != 1234 {
17 t.Fatal("Parsing '1234' did not succeed")
18 }
19
20
21
22
23
24
31
32 p, err = ParsePort("asdf")
33
34 if err == nil || p != 0 {
35 t.Fatal("Parsing port 'asdf' succeeded")
36 }
37
38 p, err = ParsePort("1asdf")
39
40 if err == nil || p != 0 {
41 t.Fatal("Parsing port '1asdf' succeeded")
42 }
43 }
44
45 func TestParsePortRangeToInt(t *testing.T) {
46 var (
47 begin int
48 end int
49 err error
50 )
51
52 type TestRange struct {
53 Range string
54 Begin int
55 End int
56 }
57 validRanges := []TestRange{
58 {"1234", 1234, 1234},
59 {"1234-1234", 1234, 1234},
60 {"1234-1235", 1234, 1235},
61 {"8000-9000", 8000, 9000},
62 {"0", 0, 0},
63 {"0-0", 0, 0},
64 }
65
66 for _, r := range validRanges {
67 begin, end, err = ParsePortRangeToInt(r.Range)
68
69 if err != nil || begin != r.Begin {
70 t.Fatalf("Parsing port range '%s' did not succeed. Expected begin %d, got %d", r.Range, r.Begin, begin)
71 }
72 if err != nil || end != r.End {
73 t.Fatalf("Parsing port range '%s' did not succeed. Expected end %d, got %d", r.Range, r.End, end)
74 }
75 }
76
77 invalidRanges := []string{
78 "asdf",
79 "1asdf",
80 "9000-8000",
81 "9000-",
82 "-8000",
83 "-8000-",
84 }
85
86 for _, r := range invalidRanges {
87 begin, end, err = ParsePortRangeToInt(r)
88
89 if err == nil || begin != 0 || end != 0 {
90 t.Fatalf("Parsing port range '%s' succeeded", r)
91 }
92 }
93 }
94
95 func TestPort(t *testing.T) {
96 p, err := NewPort("tcp", "1234")
97 if err != nil {
98 t.Fatalf("tcp, 1234 had a parsing issue: %v", err)
99 }
100
101 if string(p) != "1234/tcp" {
102 t.Fatal("tcp, 1234 did not result in the string 1234/tcp")
103 }
104
105 if p.Proto() != "tcp" {
106 t.Fatal("protocol was not tcp")
107 }
108
109 if p.Port() != "1234" {
110 t.Fatal("port string value was not 1234")
111 }
112
113 if p.Int() != 1234 {
114 t.Fatal("port int value was not 1234")
115 }
116
117 _, err = NewPort("tcp", "asd1234")
118 if err == nil {
119 t.Fatal("tcp, asd1234 was supposed to fail")
120 }
121
122 _, err = NewPort("tcp", "1234-1230")
123 if err == nil {
124 t.Fatal("tcp, 1234-1230 was supposed to fail")
125 }
126
127 p, err = NewPort("tcp", "1234-1242")
128 if err != nil {
129 t.Fatalf("tcp, 1234-1242 had a parsing issue: %v", err)
130 }
131
132 if string(p) != "1234-1242/tcp" {
133 t.Fatal("tcp, 1234-1242 did not result in the string 1234-1242/tcp")
134 }
135 }
136
137 func TestSplitProtoPort(t *testing.T) {
138 var (
139 proto string
140 port string
141 )
142
143 proto, port = SplitProtoPort("1234/tcp")
144
145 if proto != "tcp" || port != "1234" {
146 t.Fatal("Could not split 1234/tcp properly")
147 }
148
149 proto, port = SplitProtoPort("")
150
151 if proto != "" || port != "" {
152 t.Fatal("parsing an empty string yielded surprising results", proto, port)
153 }
154
155 proto, port = SplitProtoPort("1234")
156
157 if proto != "tcp" || port != "1234" {
158 t.Fatal("tcp is not the default protocol for portspec '1234'", proto, port)
159 }
160
161 proto, port = SplitProtoPort("1234/")
162
163 if proto != "tcp" || port != "1234" {
164 t.Fatal("parsing '1234/' yielded:" + port + "/" + proto)
165 }
166
167 proto, port = SplitProtoPort("/tcp")
168
169 if proto != "" || port != "" {
170 t.Fatal("parsing '/tcp' yielded:" + port + "/" + proto)
171 }
172 }
173
174 func TestParsePortSpecFull(t *testing.T) {
175 portMappings, err := ParsePortSpec("0.0.0.0:1234-1235:3333-3334/tcp")
176 if err != nil {
177 t.Fatalf("expected nil error, got: %v", err)
178 }
179
180 expected := []PortMapping{
181 {
182 Port: "3333/tcp",
183 Binding: PortBinding{
184 HostIP: "0.0.0.0",
185 HostPort: "1234",
186 },
187 },
188 {
189 Port: "3334/tcp",
190 Binding: PortBinding{
191 HostIP: "0.0.0.0",
192 HostPort: "1235",
193 },
194 },
195 }
196
197 if !reflect.DeepEqual(expected, portMappings) {
198 t.Fatalf("wrong port mappings: got=%v, want=%v", portMappings, expected)
199 }
200 }
201
202 func TestPartPortSpecIPV6(t *testing.T) {
203 type test struct {
204 name string
205 spec string
206 expected []PortMapping
207 }
208 cases := []test{
209 {
210 name: "square angled IPV6 without host port",
211 spec: "[2001:4860:0:2001::68]::333",
212 expected: []PortMapping{
213 {
214 Port: "333/tcp",
215 Binding: PortBinding{
216 HostIP: "2001:4860:0:2001::68",
217 HostPort: "",
218 },
219 },
220 },
221 },
222 {
223 name: "square angled IPV6 with host port",
224 spec: "[::1]:80:80",
225 expected: []PortMapping{
226 {
227 Port: "80/tcp",
228 Binding: PortBinding{
229 HostIP: "::1",
230 HostPort: "80",
231 },
232 },
233 },
234 },
235 {
236 name: "IPV6 without host port",
237 spec: "2001:4860:0:2001::68::333",
238 expected: []PortMapping{
239 {
240 Port: "333/tcp",
241 Binding: PortBinding{
242 HostIP: "2001:4860:0:2001::68",
243 HostPort: "",
244 },
245 },
246 },
247 },
248 {
249 name: "IPV6 with host port",
250 spec: "::1:80:80",
251 expected: []PortMapping{
252 {
253 Port: "80/tcp",
254 Binding: PortBinding{
255 HostIP: "::1",
256 HostPort: "80",
257 },
258 },
259 },
260 },
261 {
262 name: ":: IPV6, without host port",
263 spec: "::::80",
264 expected: []PortMapping{
265 {
266 Port: "80/tcp",
267 Binding: PortBinding{
268 HostIP: "::",
269 HostPort: "",
270 },
271 },
272 },
273 },
274 }
275 for _, c := range cases {
276 t.Run(c.name, func(t *testing.T) {
277 portMappings, err := ParsePortSpec(c.spec)
278 if err != nil {
279 t.Fatalf("expected nil error, got: %v", err)
280 }
281 if !reflect.DeepEqual(c.expected, portMappings) {
282 t.Fatalf("wrong port mappings: got=%v, want=%v", portMappings, c.expected)
283 }
284 })
285 }
286 }
287
288 func TestParsePortSpecs(t *testing.T) {
289 var (
290 portMap map[Port]struct{}
291 bindingMap map[Port][]PortBinding
292 err error
293 )
294
295 portMap, bindingMap, err = ParsePortSpecs([]string{"1234/tcp", "2345/udp", "3456/sctp"})
296
297 if err != nil {
298 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
299 }
300
301 if _, ok := portMap[Port("1234/tcp")]; !ok {
302 t.Fatal("1234/tcp was not parsed properly")
303 }
304
305 if _, ok := portMap[Port("2345/udp")]; !ok {
306 t.Fatal("2345/udp was not parsed properly")
307 }
308
309 if _, ok := portMap[Port("3456/sctp")]; !ok {
310 t.Fatal("3456/sctp was not parsed properly")
311 }
312
313 for portspec, bindings := range bindingMap {
314 if len(bindings) != 1 {
315 t.Fatalf("%s should have exactly one binding", portspec)
316 }
317
318 if bindings[0].HostIP != "" {
319 t.Fatalf("HostIP should not be set for %s", portspec)
320 }
321
322 if bindings[0].HostPort != "" {
323 t.Fatalf("HostPort should not be set for %s", portspec)
324 }
325 }
326
327 portMap, bindingMap, err = ParsePortSpecs([]string{"1234:1234/tcp", "2345:2345/udp", "3456:3456/sctp"})
328
329 if err != nil {
330 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
331 }
332
333 if _, ok := portMap[Port("1234/tcp")]; !ok {
334 t.Fatal("1234/tcp was not parsed properly")
335 }
336
337 if _, ok := portMap[Port("2345/udp")]; !ok {
338 t.Fatal("2345/udp was not parsed properly")
339 }
340
341 if _, ok := portMap[Port("3456/sctp")]; !ok {
342 t.Fatal("3456/sctp was not parsed properly")
343 }
344
345 for portspec, bindings := range bindingMap {
346 _, port := SplitProtoPort(string(portspec))
347
348 if len(bindings) != 1 {
349 t.Fatalf("%s should have exactly one binding", portspec)
350 }
351
352 if bindings[0].HostIP != "" {
353 t.Fatalf("HostIP should not be set for %s", portspec)
354 }
355
356 if bindings[0].HostPort != port {
357 t.Fatalf("HostPort should be %s for %s", port, portspec)
358 }
359 }
360
361 portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234:1234/tcp", "0.0.0.0:2345:2345/udp", "0.0.0.0:3456:3456/sctp"})
362
363 if err != nil {
364 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
365 }
366
367 if _, ok := portMap[Port("1234/tcp")]; !ok {
368 t.Fatal("1234/tcp was not parsed properly")
369 }
370
371 if _, ok := portMap[Port("2345/udp")]; !ok {
372 t.Fatal("2345/udp was not parsed properly")
373 }
374
375 if _, ok := portMap[Port("3456/sctp")]; !ok {
376 t.Fatal("3456/sctp was not parsed properly")
377 }
378
379 for portspec, bindings := range bindingMap {
380 _, port := SplitProtoPort(string(portspec))
381
382 if len(bindings) != 1 {
383 t.Fatalf("%s should have exactly one binding", portspec)
384 }
385
386 if bindings[0].HostIP != "0.0.0.0" {
387 t.Fatalf("HostIP is not 0.0.0.0 for %s", portspec)
388 }
389
390 if bindings[0].HostPort != port {
391 t.Fatalf("HostPort should be %s for %s", port, portspec)
392 }
393 }
394
395 _, _, err = ParsePortSpecs([]string{"localhost:1234:1234/tcp"})
396
397 if err == nil {
398 t.Fatal("Received no error while trying to parse a hostname instead of ip")
399 }
400 }
401
402 func TestParsePortSpecsWithRange(t *testing.T) {
403 var (
404 portMap map[Port]struct{}
405 bindingMap map[Port][]PortBinding
406 err error
407 )
408
409 portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236/tcp", "2345-2347/udp", "3456-3458/sctp"})
410
411 if err != nil {
412 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
413 }
414
415 if _, ok := portMap[Port("1235/tcp")]; !ok {
416 t.Fatal("1234/tcp was not parsed properly")
417 }
418
419 if _, ok := portMap[Port("2346/udp")]; !ok {
420 t.Fatal("2345/udp was not parsed properly")
421 }
422
423 if _, ok := portMap[Port("3456/sctp")]; !ok {
424 t.Fatal("3456/sctp was not parsed properly")
425 }
426
427 for portspec, bindings := range bindingMap {
428 if len(bindings) != 1 {
429 t.Fatalf("%s should have exactly one binding", portspec)
430 }
431
432 if bindings[0].HostIP != "" {
433 t.Fatalf("HostIP should not be set for %s", portspec)
434 }
435
436 if bindings[0].HostPort != "" {
437 t.Fatalf("HostPort should not be set for %s", portspec)
438 }
439 }
440
441 portMap, bindingMap, err = ParsePortSpecs([]string{"1234-1236:1234-1236/tcp", "2345-2347:2345-2347/udp", "3456-3458:3456-3458/sctp"})
442
443 if err != nil {
444 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
445 }
446
447 if _, ok := portMap[Port("1235/tcp")]; !ok {
448 t.Fatal("1234/tcp was not parsed properly")
449 }
450
451 if _, ok := portMap[Port("2346/udp")]; !ok {
452 t.Fatal("2345/udp was not parsed properly")
453 }
454
455 if _, ok := portMap[Port("3456/sctp")]; !ok {
456 t.Fatal("3456/sctp was not parsed properly")
457 }
458
459 for portspec, bindings := range bindingMap {
460 _, port := SplitProtoPort(string(portspec))
461 if len(bindings) != 1 {
462 t.Fatalf("%s should have exactly one binding", portspec)
463 }
464
465 if bindings[0].HostIP != "" {
466 t.Fatalf("HostIP should not be set for %s", portspec)
467 }
468
469 if bindings[0].HostPort != port {
470 t.Fatalf("HostPort should be %s for %s", port, portspec)
471 }
472 }
473
474 portMap, bindingMap, err = ParsePortSpecs([]string{"0.0.0.0:1234-1236:1234-1236/tcp", "0.0.0.0:2345-2347:2345-2347/udp", "0.0.0.0:3456-3458:3456-3458/sctp"})
475
476 if err != nil {
477 t.Fatalf("Error while processing ParsePortSpecs: %s", err)
478 }
479
480 if _, ok := portMap[Port("1235/tcp")]; !ok {
481 t.Fatal("1234/tcp was not parsed properly")
482 }
483
484 if _, ok := portMap[Port("2346/udp")]; !ok {
485 t.Fatal("2345/udp was not parsed properly")
486 }
487
488 if _, ok := portMap[Port("3456/sctp")]; !ok {
489 t.Fatal("3456/sctp was not parsed properly")
490 }
491
492 for portspec, bindings := range bindingMap {
493 _, port := SplitProtoPort(string(portspec))
494 if len(bindings) != 1 || bindings[0].HostIP != "0.0.0.0" || bindings[0].HostPort != port {
495 t.Fatalf("Expect single binding to port %s but found %s", port, bindings)
496 }
497 }
498
499 _, _, err = ParsePortSpecs([]string{"localhost:1234-1236:1234-1236/tcp"})
500
501 if err == nil {
502 t.Fatal("Received no error while trying to parse a hostname instead of ip")
503 }
504 }
505
506 func TestParseNetworkOptsPrivateOnly(t *testing.T) {
507 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::80"})
508 if err != nil {
509 t.Fatal(err)
510 }
511 if len(ports) != 1 {
512 t.Logf("Expected 1 got %d", len(ports))
513 t.FailNow()
514 }
515 if len(bindings) != 1 {
516 t.Logf("Expected 1 got %d", len(bindings))
517 t.FailNow()
518 }
519 for k := range ports {
520 if k.Proto() != "tcp" {
521 t.Logf("Expected tcp got %s", k.Proto())
522 t.Fail()
523 }
524 if k.Port() != "80" {
525 t.Logf("Expected 80 got %s", k.Port())
526 t.Fail()
527 }
528 b, exists := bindings[k]
529 if !exists {
530 t.Log("Binding does not exist")
531 t.FailNow()
532 }
533 if len(b) != 1 {
534 t.Logf("Expected 1 got %d", len(b))
535 t.FailNow()
536 }
537 s := b[0]
538 if s.HostPort != "" {
539 t.Logf("Expected \"\" got %s", s.HostPort)
540 t.Fail()
541 }
542 if s.HostIP != "192.168.1.100" {
543 t.Fail()
544 }
545 }
546 }
547
548 func TestParseNetworkOptsPublic(t *testing.T) {
549 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:8080:80"})
550 if err != nil {
551 t.Fatal(err)
552 }
553 if len(ports) != 1 {
554 t.Logf("Expected 1 got %d", len(ports))
555 t.FailNow()
556 }
557 if len(bindings) != 1 {
558 t.Logf("Expected 1 got %d", len(bindings))
559 t.FailNow()
560 }
561 for k := range ports {
562 if k.Proto() != "tcp" {
563 t.Logf("Expected tcp got %s", k.Proto())
564 t.Fail()
565 }
566 if k.Port() != "80" {
567 t.Logf("Expected 80 got %s", k.Port())
568 t.Fail()
569 }
570 b, exists := bindings[k]
571 if !exists {
572 t.Log("Binding does not exist")
573 t.FailNow()
574 }
575 if len(b) != 1 {
576 t.Logf("Expected 1 got %d", len(b))
577 t.FailNow()
578 }
579 s := b[0]
580 if s.HostPort != "8080" {
581 t.Logf("Expected 8080 got %s", s.HostPort)
582 t.Fail()
583 }
584 if s.HostIP != "192.168.1.100" {
585 t.Fail()
586 }
587 }
588 }
589
590 func TestParseNetworkOptsPublicNoPort(t *testing.T) {
591 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100"})
592
593 if err == nil {
594 t.Logf("Expected error Invalid containerPort")
595 t.Fail()
596 }
597 if ports != nil {
598 t.Logf("Expected nil got %s", ports)
599 t.Fail()
600 }
601 if bindings != nil {
602 t.Logf("Expected nil got %s", bindings)
603 t.Fail()
604 }
605 }
606
607 func TestParseNetworkOptsNegativePorts(t *testing.T) {
608 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100:-1:-1"})
609
610 if err == nil {
611 t.Fail()
612 }
613 if len(ports) != 0 {
614 t.Logf("Expected nil got %d", len(ports))
615 t.Fail()
616 }
617 if len(bindings) != 0 {
618 t.Logf("Expected 0 got %d", len(bindings))
619 t.Fail()
620 }
621 }
622
623 func TestParseNetworkOptsUdp(t *testing.T) {
624 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::6000/udp"})
625 if err != nil {
626 t.Fatal(err)
627 }
628 if len(ports) != 1 {
629 t.Logf("Expected 1 got %d", len(ports))
630 t.FailNow()
631 }
632 if len(bindings) != 1 {
633 t.Logf("Expected 1 got %d", len(bindings))
634 t.FailNow()
635 }
636 for k := range ports {
637 if k.Proto() != "udp" {
638 t.Logf("Expected udp got %s", k.Proto())
639 t.Fail()
640 }
641 if k.Port() != "6000" {
642 t.Logf("Expected 6000 got %s", k.Port())
643 t.Fail()
644 }
645 b, exists := bindings[k]
646 if !exists {
647 t.Log("Binding does not exist")
648 t.FailNow()
649 }
650 if len(b) != 1 {
651 t.Logf("Expected 1 got %d", len(b))
652 t.FailNow()
653 }
654 s := b[0]
655 if s.HostPort != "" {
656 t.Logf("Expected \"\" got %s", s.HostPort)
657 t.Fail()
658 }
659 if s.HostIP != "192.168.1.100" {
660 t.Fail()
661 }
662 }
663 }
664
665 func TestParseNetworkOptsSctp(t *testing.T) {
666 ports, bindings, err := ParsePortSpecs([]string{"192.168.1.100::6000/sctp"})
667 if err != nil {
668 t.Fatal(err)
669 }
670 if len(ports) != 1 {
671 t.Logf("Expected 1 got %d", len(ports))
672 t.FailNow()
673 }
674 if len(bindings) != 1 {
675 t.Logf("Expected 1 got %d", len(bindings))
676 t.FailNow()
677 }
678 for k := range ports {
679 if k.Proto() != "sctp" {
680 t.Logf("Expected sctp got %s", k.Proto())
681 t.Fail()
682 }
683 if k.Port() != "6000" {
684 t.Logf("Expected 6000 got %s", k.Port())
685 t.Fail()
686 }
687 b, exists := bindings[k]
688 if !exists {
689 t.Log("Binding does not exist")
690 t.FailNow()
691 }
692 if len(b) != 1 {
693 t.Logf("Expected 1 got %d", len(b))
694 t.FailNow()
695 }
696 s := b[0]
697 if s.HostPort != "" {
698 t.Logf("Expected \"\" got %s", s.HostPort)
699 t.Fail()
700 }
701 if s.HostIP != "192.168.1.100" {
702 t.Fail()
703 }
704 }
705 }
706
View as plain text