1
16
17 package validation
18
19 import (
20 "strings"
21 "testing"
22
23 "k8s.io/apimachinery/pkg/util/validation/field"
24 )
25
26 func TestIsDNS1123Label(t *testing.T) {
27 goodValues := []string{
28 "a", "ab", "abc", "a1", "a-1", "a--1--2--b",
29 "0", "01", "012", "1a", "1-a", "1--a--b--2",
30 strings.Repeat("a", 63),
31 }
32 for _, val := range goodValues {
33 if msgs := IsDNS1123Label(val); len(msgs) != 0 {
34 t.Errorf("expected true for '%s': %v", val, msgs)
35 }
36 }
37
38 badValues := []string{
39 "", "A", "ABC", "aBc", "A1", "A-1", "1-A",
40 "-", "a-", "-a", "1-", "-1",
41 "_", "a_", "_a", "a_b", "1_", "_1", "1_2",
42 ".", "a.", ".a", "a.b", "1.", ".1", "1.2",
43 " ", "a ", " a", "a b", "1 ", " 1", "1 2",
44 strings.Repeat("a", 64),
45 }
46 for _, val := range badValues {
47 if msgs := IsDNS1123Label(val); len(msgs) == 0 {
48 t.Errorf("expected false for '%s'", val)
49 }
50 }
51 }
52
53 func TestIsDNS1123Subdomain(t *testing.T) {
54 goodValues := []string{
55 "a", "ab", "abc", "a1", "a-1", "a--1--2--b",
56 "0", "01", "012", "1a", "1-a", "1--a--b--2",
57 "a.a", "ab.a", "abc.a", "a1.a", "a-1.a", "a--1--2--b.a",
58 "a.1", "ab.1", "abc.1", "a1.1", "a-1.1", "a--1--2--b.1",
59 "0.a", "01.a", "012.a", "1a.a", "1-a.a", "1--a--b--2",
60 "0.1", "01.1", "012.1", "1a.1", "1-a.1", "1--a--b--2.1",
61 "a.b.c.d.e", "aa.bb.cc.dd.ee", "1.2.3.4.5", "11.22.33.44.55",
62 strings.Repeat("a", 253),
63 }
64 for _, val := range goodValues {
65 if msgs := IsDNS1123Subdomain(val); len(msgs) != 0 {
66 t.Errorf("expected true for '%s': %v", val, msgs)
67 }
68 }
69
70 badValues := []string{
71 "", "A", "ABC", "aBc", "A1", "A-1", "1-A",
72 "-", "a-", "-a", "1-", "-1",
73 "_", "a_", "_a", "a_b", "1_", "_1", "1_2",
74 ".", "a.", ".a", "a..b", "1.", ".1", "1..2",
75 " ", "a ", " a", "a b", "1 ", " 1", "1 2",
76 "A.a", "aB.a", "ab.A", "A1.a", "a1.A",
77 "A.1", "aB.1", "A1.1", "1A.1",
78 "0.A", "01.A", "012.A", "1A.a", "1a.A",
79 "A.B.C.D.E", "AA.BB.CC.DD.EE", "a.B.c.d.e", "aa.bB.cc.dd.ee",
80 "a@b", "a,b", "a_b", "a;b",
81 "a:b", "a%b", "a?b", "a$b",
82 strings.Repeat("a", 254),
83 }
84 for _, val := range badValues {
85 if msgs := IsDNS1123Subdomain(val); len(msgs) == 0 {
86 t.Errorf("expected false for '%s'", val)
87 }
88 }
89 }
90
91 func TestIsDNS1035Label(t *testing.T) {
92 goodValues := []string{
93 "a", "ab", "abc", "a1", "a-1", "a--1--2--b",
94 strings.Repeat("a", 63),
95 }
96 for _, val := range goodValues {
97 if msgs := IsDNS1035Label(val); len(msgs) != 0 {
98 t.Errorf("expected true for '%s': %v", val, msgs)
99 }
100 }
101
102 badValues := []string{
103 "0", "01", "012", "1a", "1-a", "1--a--b--2",
104 "", "A", "ABC", "aBc", "A1", "A-1", "1-A",
105 "-", "a-", "-a", "1-", "-1",
106 "_", "a_", "_a", "a_b", "1_", "_1", "1_2",
107 ".", "a.", ".a", "a.b", "1.", ".1", "1.2",
108 " ", "a ", " a", "a b", "1 ", " 1", "1 2",
109 strings.Repeat("a", 64),
110 }
111 for _, val := range badValues {
112 if msgs := IsDNS1035Label(val); len(msgs) == 0 {
113 t.Errorf("expected false for '%s'", val)
114 }
115 }
116 }
117
118 func TestIsCIdentifier(t *testing.T) {
119 goodValues := []string{
120 "a", "ab", "abc", "a1", "_a", "a_", "a_b", "a_1", "a__1__2__b", "__abc_123",
121 "A", "AB", "AbC", "A1", "_A", "A_", "A_B", "A_1", "A__1__2__B", "__123_ABC",
122 }
123 for _, val := range goodValues {
124 if msgs := IsCIdentifier(val); len(msgs) != 0 {
125 t.Errorf("expected true for '%s': %v", val, msgs)
126 }
127 }
128
129 badValues := []string{
130 "", "1", "123", "1a",
131 "-", "a-", "-a", "1-", "-1", "1_", "1_2",
132 ".", "a.", ".a", "a.b", "1.", ".1", "1.2",
133 " ", "a ", " a", "a b", "1 ", " 1", "1 2",
134 "#a#",
135 }
136 for _, val := range badValues {
137 if msgs := IsCIdentifier(val); len(msgs) == 0 {
138 t.Errorf("expected false for '%s'", val)
139 }
140 }
141 }
142
143 func TestIsValidPortNum(t *testing.T) {
144 goodValues := []int{1, 2, 1000, 16384, 32768, 65535}
145 for _, val := range goodValues {
146 if msgs := IsValidPortNum(val); len(msgs) != 0 {
147 t.Errorf("expected true for %d, got %v", val, msgs)
148 }
149 }
150
151 badValues := []int{0, -1, 65536, 100000}
152 for _, val := range badValues {
153 if msgs := IsValidPortNum(val); len(msgs) == 0 {
154 t.Errorf("expected false for %d", val)
155 }
156 }
157 }
158
159 func TestIsInRange(t *testing.T) {
160 goodValues := []struct {
161 value int
162 min int
163 max int
164 }{{1, 0, 10}, {5, 5, 20}, {25, 10, 25}}
165 for _, val := range goodValues {
166 if msgs := IsInRange(val.value, val.min, val.max); len(msgs) > 0 {
167 t.Errorf("expected no errors for %#v, but got %v", val, msgs)
168 }
169 }
170
171 badValues := []struct {
172 value int
173 min int
174 max int
175 }{{1, 2, 10}, {5, -4, 2}, {25, 100, 120}}
176 for _, val := range badValues {
177 if msgs := IsInRange(val.value, val.min, val.max); len(msgs) == 0 {
178 t.Errorf("expected errors for %#v", val)
179 }
180 }
181 }
182
183 func createGroupIDs(ids ...int64) []int64 {
184 var output []int64
185 for _, id := range ids {
186 output = append(output, int64(id))
187 }
188 return output
189 }
190
191 func createUserIDs(ids ...int64) []int64 {
192 var output []int64
193 for _, id := range ids {
194 output = append(output, int64(id))
195 }
196 return output
197 }
198
199 func TestIsValidGroupID(t *testing.T) {
200 goodValues := createGroupIDs(0, 1, 1000, 65535, 2147483647)
201 for _, val := range goodValues {
202 if msgs := IsValidGroupID(val); len(msgs) != 0 {
203 t.Errorf("expected true for '%d': %v", val, msgs)
204 }
205 }
206
207 badValues := createGroupIDs(-1, -1003, 2147483648, 4147483647)
208 for _, val := range badValues {
209 if msgs := IsValidGroupID(val); len(msgs) == 0 {
210 t.Errorf("expected false for '%d'", val)
211 }
212 }
213 }
214
215 func TestIsValidUserID(t *testing.T) {
216 goodValues := createUserIDs(0, 1, 1000, 65535, 2147483647)
217 for _, val := range goodValues {
218 if msgs := IsValidUserID(val); len(msgs) != 0 {
219 t.Errorf("expected true for '%d': %v", val, msgs)
220 }
221 }
222
223 badValues := createUserIDs(-1, -1003, 2147483648, 4147483647)
224 for _, val := range badValues {
225 if msgs := IsValidUserID(val); len(msgs) == 0 {
226 t.Errorf("expected false for '%d'", val)
227 }
228 }
229 }
230
231 func TestIsValidPortName(t *testing.T) {
232 goodValues := []string{"telnet", "re-mail-ck", "pop3", "a", "a-1", "1-a", "a-1-b-2-c", "1-a-2-b-3"}
233 for _, val := range goodValues {
234 if msgs := IsValidPortName(val); len(msgs) != 0 {
235 t.Errorf("expected true for %q: %v", val, msgs)
236 }
237 }
238
239 badValues := []string{"longerthan15characters", "", strings.Repeat("a", 16), "12345", "1-2-3-4", "-begin", "end-", "two--hyphens", "whois++"}
240 for _, val := range badValues {
241 if msgs := IsValidPortName(val); len(msgs) == 0 {
242 t.Errorf("expected false for %q", val)
243 }
244 }
245 }
246
247 func TestIsQualifiedName(t *testing.T) {
248 successCases := []string{
249 "simple",
250 "now-with-dashes",
251 "1-starts-with-num",
252 "1234",
253 "simple/simple",
254 "now-with-dashes/simple",
255 "now-with-dashes/now-with-dashes",
256 "now.with.dots/simple",
257 "now-with.dashes-and.dots/simple",
258 "1-num.2-num/3-num",
259 "1234/5678",
260 "1.2.3.4/5678",
261 "Uppercase_Is_OK_123",
262 "example.com/Uppercase_Is_OK_123",
263 "requests.storage-foo",
264 strings.Repeat("a", 63),
265 strings.Repeat("a", 253) + "/" + strings.Repeat("b", 63),
266 }
267 for i := range successCases {
268 if errs := IsQualifiedName(successCases[i]); len(errs) != 0 {
269 t.Errorf("case[%d]: %q: expected success: %v", i, successCases[i], errs)
270 }
271 }
272
273 errorCases := []string{
274 "nospecialchars%^=@",
275 "cantendwithadash-",
276 "-cantstartwithadash-",
277 "only/one/slash",
278 "Example.com/abc",
279 "example_com/abc",
280 "example.com/",
281 "/simple",
282 strings.Repeat("a", 64),
283 strings.Repeat("a", 254) + "/abc",
284 }
285 for i := range errorCases {
286 if errs := IsQualifiedName(errorCases[i]); len(errs) == 0 {
287 t.Errorf("case[%d]: %q: expected failure", i, errorCases[i])
288 }
289 }
290 }
291
292 func TestIsValidLabelValue(t *testing.T) {
293 successCases := []string{
294 "simple",
295 "now-with-dashes",
296 "1-starts-with-num",
297 "end-with-num-1",
298 "1234",
299 strings.Repeat("a", 63),
300 "",
301 }
302 for i := range successCases {
303 if errs := IsValidLabelValue(successCases[i]); len(errs) != 0 {
304 t.Errorf("case %s expected success: %v", successCases[i], errs)
305 }
306 }
307
308 errorCases := []string{
309 "nospecialchars%^=@",
310 "Tama-nui-te-rā.is.Māori.sun",
311 "\\backslashes\\are\\bad",
312 "-starts-with-dash",
313 "ends-with-dash-",
314 ".starts.with.dot",
315 "ends.with.dot.",
316 strings.Repeat("a", 64),
317 }
318 for i := range errorCases {
319 if errs := IsValidLabelValue(errorCases[i]); len(errs) == 0 {
320 t.Errorf("case[%d] expected failure", i)
321 }
322 }
323 }
324
325 func TestIsValidIP(t *testing.T) {
326 for _, tc := range []struct {
327 name string
328 in string
329 family int
330 err string
331 }{
332
333 {
334 name: "ipv4",
335 in: "1.2.3.4",
336 family: 4,
337 },
338 {
339 name: "ipv4, all zeros",
340 in: "0.0.0.0",
341 family: 4,
342 },
343 {
344 name: "ipv4, max",
345 in: "255.255.255.255",
346 family: 4,
347 },
348 {
349 name: "ipv6",
350 in: "1234::abcd",
351 family: 6,
352 },
353 {
354 name: "ipv6, all zeros, collapsed",
355 in: "::",
356 family: 6,
357 },
358 {
359 name: "ipv6, max",
360 in: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
361 family: 6,
362 },
363
364
365 {
366 name: "ipv6, all zeros, expanded (non-canonical)",
367 in: "0:0:0:0:0:0:0:0",
368 family: 6,
369 },
370 {
371 name: "ipv6, leading 0s (non-canonical)",
372 in: "0001:002:03:4::",
373 family: 6,
374 },
375 {
376 name: "ipv6, capital letters (non-canonical)",
377 in: "1234::ABCD",
378 family: 6,
379 },
380
381
382 {
383 name: "ipv4 with leading 0s",
384 in: "1.1.1.01",
385 family: 4,
386 },
387 {
388 name: "ipv4-in-ipv6 value",
389 in: "::ffff:1.1.1.1",
390 family: 4,
391 },
392
393
394 {
395 name: "empty string",
396 in: "",
397 err: "must be a valid IP address",
398 },
399 {
400 name: "junk",
401 in: "aaaaaaa",
402 err: "must be a valid IP address",
403 },
404 {
405 name: "domain name",
406 in: "myhost.mydomain",
407 err: "must be a valid IP address",
408 },
409 {
410 name: "cidr",
411 in: "1.2.3.0/24",
412 err: "must be a valid IP address",
413 },
414 {
415 name: "ipv4 with out-of-range octets",
416 in: "1.2.3.400",
417 err: "must be a valid IP address",
418 },
419 {
420 name: "ipv4 with negative octets",
421 in: "-1.0.0.0",
422 err: "must be a valid IP address",
423 },
424 {
425 name: "ipv6 with out-of-range segment",
426 in: "2001:db8::10005",
427 err: "must be a valid IP address",
428 },
429 {
430 name: "ipv4:port",
431 in: "1.2.3.4:80",
432 err: "must be a valid IP address",
433 },
434 {
435 name: "ipv6 with brackets",
436 in: "[2001:db8::1]",
437 err: "must be a valid IP address",
438 },
439 {
440 name: "[ipv6]:port",
441 in: "[2001:db8::1]:80",
442 err: "must be a valid IP address",
443 },
444 {
445 name: "host:port",
446 in: "example.com:80",
447 err: "must be a valid IP address",
448 },
449 {
450 name: "ipv6 with zone",
451 in: "1234::abcd%eth0",
452 err: "must be a valid IP address",
453 },
454 {
455 name: "ipv4 with zone",
456 in: "169.254.0.0%eth0",
457 err: "must be a valid IP address",
458 },
459 } {
460 t.Run(tc.name, func(t *testing.T) {
461 errs := IsValidIP(field.NewPath(""), tc.in)
462 if tc.err == "" {
463 if len(errs) != 0 {
464 t.Errorf("expected %q to be valid but got: %v", tc.in, errs)
465 }
466 } else {
467 if len(errs) != 1 {
468 t.Errorf("expected %q to have 1 error but got: %v", tc.in, errs)
469 } else if !strings.Contains(errs[0].Detail, tc.err) {
470 t.Errorf("expected error for %q to contain %q but got: %q", tc.in, tc.err, errs[0].Detail)
471 }
472 }
473
474 errs = IsValidIPv4Address(field.NewPath(""), tc.in)
475 if tc.family == 4 {
476 if len(errs) != 0 {
477 t.Errorf("expected %q to pass IsValidIPv4Address but got: %v", tc.in, errs)
478 }
479 } else {
480 if len(errs) == 0 {
481 t.Errorf("expected %q to fail IsValidIPv4Address", tc.in)
482 }
483 }
484
485 errs = IsValidIPv6Address(field.NewPath(""), tc.in)
486 if tc.family == 6 {
487 if len(errs) != 0 {
488 t.Errorf("expected %q to pass IsValidIPv6Address but got: %v", tc.in, errs)
489 }
490 } else {
491 if len(errs) == 0 {
492 t.Errorf("expected %q to fail IsValidIPv6Address", tc.in)
493 }
494 }
495 })
496 }
497 }
498
499 func TestIsValidCIDR(t *testing.T) {
500 for _, tc := range []struct {
501 name string
502 in string
503 err string
504 }{
505
506 {
507 name: "ipv4",
508 in: "1.0.0.0/8",
509 },
510 {
511 name: "ipv4, all IPs",
512 in: "0.0.0.0/0",
513 },
514 {
515 name: "ipv4, single IP",
516 in: "1.1.1.1/32",
517 },
518 {
519 name: "ipv6",
520 in: "2001:4860:4860::/48",
521 },
522 {
523 name: "ipv6, all IPs",
524 in: "::/0",
525 },
526 {
527 name: "ipv6, single IP",
528 in: "::1/128",
529 },
530
531
532 {
533 name: "ipv6, extra 0s (non-canonical)",
534 in: "2a00:79e0:2:0::/64",
535 },
536 {
537 name: "ipv6, capital letters (non-canonical)",
538 in: "2001:DB8::/64",
539 },
540
541
542 {
543 name: "ipv4 with leading 0s",
544 in: "1.1.01.0/24",
545 },
546 {
547 name: "ipv4-in-ipv6 with ipv4-sized prefix",
548 in: "::ffff:1.1.1.0/24",
549 },
550 {
551 name: "ipv4-in-ipv6 with ipv6-sized prefix",
552 in: "::ffff:1.1.1.0/120",
553 },
554 {
555 name: "ipv4 with bits past prefix",
556 in: "1.2.3.4/24",
557 },
558 {
559 name: "ipv6 with bits past prefix",
560 in: "2001:db8::1/64",
561 },
562 {
563 name: "prefix length with leading 0s",
564 in: "192.168.0.0/016",
565 },
566
567
568 {
569 name: "empty string",
570 in: "",
571 err: "must be a valid CIDR value",
572 },
573 {
574 name: "junk",
575 in: "aaaaaaa",
576 err: "must be a valid CIDR value",
577 },
578 {
579 name: "IP address",
580 in: "1.2.3.4",
581 err: "must be a valid CIDR value",
582 },
583 {
584 name: "partial URL",
585 in: "192.168.0.1/healthz",
586 err: "must be a valid CIDR value",
587 },
588 {
589 name: "partial URL 2",
590 in: "192.168.0.1/0/99",
591 err: "must be a valid CIDR value",
592 },
593 {
594 name: "negative prefix length",
595 in: "192.168.0.0/-16",
596 err: "must be a valid CIDR value",
597 },
598 {
599 name: "prefix length with sign",
600 in: "192.168.0.0/+16",
601 err: "must be a valid CIDR value",
602 },
603 } {
604 t.Run(tc.name, func(t *testing.T) {
605 errs := IsValidCIDR(field.NewPath(""), tc.in)
606 if tc.err == "" {
607 if len(errs) != 0 {
608 t.Errorf("expected %q to be valid but got: %v", tc.in, errs)
609 }
610 } else {
611 if len(errs) != 1 {
612 t.Errorf("expected %q to have 1 error but got: %v", tc.in, errs)
613 } else if !strings.Contains(errs[0].Detail, tc.err) {
614 t.Errorf("expected error for %q to contain %q but got: %q", tc.in, tc.err, errs[0].Detail)
615 }
616 }
617 })
618 }
619 }
620
621 func TestIsHTTPHeaderName(t *testing.T) {
622 goodValues := []string{
623
624 "Accept-Encoding", "Host", "If-Modified-Since", "X-Forwarded-For",
625
626 "a", "ab", "abc", "a1", "-a", "a-", "a-b", "a-1", "a--1--2--b", "--abc-123",
627 "A", "AB", "AbC", "A1", "-A", "A-", "A-B", "A-1", "A--1--2--B", "--123-ABC",
628 }
629 for _, val := range goodValues {
630 if msgs := IsHTTPHeaderName(val); len(msgs) != 0 {
631 t.Errorf("expected true for '%s': %v", val, msgs)
632 }
633 }
634
635 badValues := []string{
636 "Host:", "X-Forwarded-For:", "X-@Home",
637 "", "_", "a_", "_a", "1_", "1_2", ".", "a.", ".a", "a.b", "1.", ".1", "1.2",
638 " ", "a ", " a", "a b", "1 ", " 1", "1 2", "#a#", "^", ",", ";", "=", "<",
639 "?", "@", "{",
640 }
641 for _, val := range badValues {
642 if msgs := IsHTTPHeaderName(val); len(msgs) == 0 {
643 t.Errorf("expected false for '%s'", val)
644 }
645 }
646 }
647
648 func TestIsValidPercent(t *testing.T) {
649 goodValues := []string{
650 "0%",
651 "00000%",
652 "1%",
653 "01%",
654 "99%",
655 "100%",
656 "101%",
657 }
658 for _, val := range goodValues {
659 if msgs := IsValidPercent(val); len(msgs) != 0 {
660 t.Errorf("expected true for %q: %v", val, msgs)
661 }
662 }
663
664 badValues := []string{
665 "",
666 "0",
667 "100",
668 "0.0%",
669 "99.9%",
670 "hundred",
671 " 1%",
672 "1% ",
673 "-0%",
674 "-1%",
675 "+1%",
676 }
677 for _, val := range badValues {
678 if msgs := IsValidPercent(val); len(msgs) == 0 {
679 t.Errorf("expected false for %q", val)
680 }
681 }
682 }
683
684 func TestIsConfigMapKey(t *testing.T) {
685 successCases := []string{
686 "a",
687 "good",
688 "good-good",
689 "still.good",
690 "this.is.also.good",
691 ".so.is.this",
692 "THIS_IS_GOOD",
693 "so_is_this_17",
694 }
695
696 for i := range successCases {
697 if errs := IsConfigMapKey(successCases[i]); len(errs) != 0 {
698 t.Errorf("[%d] expected success: %v", i, errs)
699 }
700 }
701
702 failureCases := []string{
703 ".",
704 "..",
705 "..bad",
706 "b*d",
707 "bad!&bad",
708 }
709
710 for i := range failureCases {
711 if errs := IsConfigMapKey(failureCases[i]); len(errs) == 0 {
712 t.Errorf("[%d] expected failure", i)
713 }
714 }
715 }
716
717 func TestIsWildcardDNS1123Subdomain(t *testing.T) {
718 goodValues := []string{
719 "*.example.com",
720 "*.bar.com",
721 "*.foo.bar.com",
722 }
723 for _, val := range goodValues {
724 if errs := IsWildcardDNS1123Subdomain(val); len(errs) != 0 {
725 t.Errorf("expected no errors for %q: %v", val, errs)
726 }
727 }
728
729 badValues := []string{
730 "*.*.bar.com",
731 "*.foo.*.com",
732 "*bar.com",
733 "f*.bar.com",
734 "*",
735 }
736 for _, val := range badValues {
737 if errs := IsWildcardDNS1123Subdomain(val); len(errs) == 0 {
738 t.Errorf("expected errors for %q", val)
739 }
740 }
741 }
742
743 func TestIsFullyQualifiedDomainName(t *testing.T) {
744 goodValues := []string{
745 "a.com",
746 "k8s.io",
747 "dev.k8s.io",
748 "dev.k8s.io.",
749 "foo.example.com",
750 "this.is.a.really.long.fqdn",
751 "bbc.co.uk",
752 "10.0.0.1",
753 "hyphens-are-good.k8s.io",
754 strings.Repeat("a", 63) + ".k8s.io",
755 strings.Repeat("a", 63) + "." + strings.Repeat("b", 63) + "." + strings.Repeat("c", 63) + "." + strings.Repeat("d", 54) + ".k8s.io",
756 }
757 for _, val := range goodValues {
758 if err := IsFullyQualifiedDomainName(field.NewPath(""), val).ToAggregate(); err != nil {
759 t.Errorf("expected no errors for %q: %v", val, err)
760 }
761 }
762
763 badValues := []string{
764 ".",
765 "...",
766 ".io",
767 "com",
768 ".com",
769 "Dev.k8s.io",
770 ".foo.example.com",
771 "*.example.com",
772 "*.bar.com",
773 "*.foo.bar.com",
774 "underscores_are_bad.k8s.io",
775 "foo@bar.example.com",
776 "http://foo.example.com",
777 strings.Repeat("a", 64) + ".k8s.io",
778 strings.Repeat("a", 63) + "." + strings.Repeat("b", 63) + "." + strings.Repeat("c", 63) + "." + strings.Repeat("d", 55) + ".k8s.io",
779 }
780 for _, val := range badValues {
781 if err := IsFullyQualifiedDomainName(field.NewPath(""), val).ToAggregate(); err == nil {
782 t.Errorf("expected errors for %q", val)
783 }
784 }
785 }
786
787 func TestIsFullyQualifiedName(t *testing.T) {
788 goodValues := []string{
789 "dev.k8s.io",
790 "foo.example.com",
791 "this.is.a.really.long.fqdn",
792 "bbc.co.uk",
793 "10.0.0.1",
794 "hyphens-are-good.k8s.io",
795 strings.Repeat("a", 246) + ".k8s.io",
796 }
797 for _, val := range goodValues {
798 if err := IsFullyQualifiedName(field.NewPath(""), val).ToAggregate(); err != nil {
799 t.Errorf("expected no errors for %q: %v", val, err)
800 }
801 }
802
803 badValues := []string{
804 "...",
805 "dev.k8s.io.",
806 ".io",
807 "Dev.k8s.io",
808 "k8s.io",
809 "*.example.com",
810 "*.bar.com",
811 "*.foo.bar.com",
812 "underscores_are_bad.k8s.io",
813 "foo@bar.example.com",
814 "http://foo.example.com",
815 strings.Repeat("a", 247) + ".k8s.io",
816 }
817 for _, val := range badValues {
818 if err := IsFullyQualifiedName(field.NewPath(""), val).ToAggregate(); err == nil {
819 t.Errorf("expected errors for %q", val)
820 }
821 }
822
823 messageTests := []struct {
824 name string
825 targetName string
826 err string
827 }{{
828 name: "name needs to be fully qualified, i.e., contains at least 2 dots",
829 targetName: "k8s.io",
830 err: "should be a domain with at least three segments separated by dots",
831 }, {
832 name: "name should not include scheme",
833 targetName: "http://foo.k8s.io",
834 err: "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
835 }, {
836 name: "email should be invalid",
837 targetName: "example@foo.k8s.io",
838 err: "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
839 }, {
840 name: "name cannot be empty",
841 targetName: "",
842 err: "Required value",
843 }, {
844 name: "name must conform to RFC 1123",
845 targetName: "A.B.C",
846 err: "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters",
847 }}
848 for _, tc := range messageTests {
849 err := IsFullyQualifiedName(field.NewPath(""), tc.targetName).ToAggregate()
850 switch {
851 case tc.err == "" && err != nil:
852 t.Errorf("%q: unexpected error: %v", tc.name, err)
853 case tc.err != "" && err == nil:
854 t.Errorf("%q: unexpected no error, expected %s", tc.name, tc.err)
855 case tc.err != "" && err != nil && !strings.Contains(err.Error(), tc.err):
856 t.Errorf("%q: expected %s, got %v", tc.name, tc.err, err)
857 }
858 }
859 }
860
861 func TestIsDomainPrefixedPath(t *testing.T) {
862 goodValues := []string{
863 "a/b",
864 "a/b/c/d",
865 "a.com/foo",
866 "a.b.c.d/foo",
867 "k8s.io/foo/bar",
868 "k8s.io/FOO/BAR",
869 "dev.k8s.io/more/path",
870 "this.is.a.really.long.fqdn/even/longer/path/just/because",
871 "bbc.co.uk/path/goes/here",
872 "10.0.0.1/foo",
873 "hyphens-are-good.k8s.io/and-in-paths-too",
874 strings.Repeat("a", 240) + ".k8s.io/a",
875 "k8s.io/" + strings.Repeat("a", 240),
876 }
877 for _, val := range goodValues {
878 if err := IsDomainPrefixedPath(field.NewPath(""), val).ToAggregate(); err != nil {
879 t.Errorf("expected no errors for %q: %v", val, err)
880 }
881 }
882
883 badValues := []string{
884 ".",
885 "...",
886 "/b",
887 "com",
888 ".com",
889 "a.b.c.d/foo?a=b",
890 "a.b.c.d/foo#a",
891 "Dev.k8s.io",
892 ".foo.example.com",
893 "*.example.com",
894 "example.com/foo{}[]@^`",
895 "underscores_are_bad.k8s.io",
896 "underscores_are_bad.k8s.io/foo",
897 "foo@bar.example.com",
898 "foo@bar.example.com/foo",
899 strings.Repeat("a", 247) + ".k8s.io",
900 }
901 for _, val := range badValues {
902 if err := IsDomainPrefixedPath(field.NewPath(""), val).ToAggregate(); err == nil {
903 t.Errorf("expected errors for %q", val)
904 }
905 }
906 }
907
908 func TestIsRelaxedEnvVarName(t *testing.T) {
909 goodValues := []string{
910 "-", ":", "_", "+a", ">a", "<a",
911 "a.", "a..", "*a", "%a", "?a",
912 "a:a", "a_a", "aAz", "~a", "|a",
913 "a0a", "a9", "/a", "a ", "#a",
914 "0a", "0 a", "'a", "(a", "@a",
915 }
916 for _, val := range goodValues {
917 if msgs := IsRelaxedEnvVarName(val); len(msgs) != 0 {
918 t.Errorf("expected true for '%s': %v", val, msgs)
919 }
920 }
921
922 badValues := []string{
923 "", "=", "a=", "1=a", "a=b", "#%=&&",
924 string(rune(1)) + "abc", string(rune(130)) + "abc",
925 "Ç ç", "Ä ä", "Ñ ñ", "Ø ø",
926 }
927
928 for _, val := range badValues {
929 if msgs := IsRelaxedEnvVarName(val); len(msgs) == 0 {
930 t.Errorf("expected false for '%s'", val)
931 }
932 }
933 }
934
View as plain text