From cc2017ec38ebfed2624e7bca5118481aa00c9687 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Wed, 27 Dec 2023 09:44:45 -0500 Subject: [PATCH] Expand IsValidIP unit tests Add more test cases, and merge the IsValidIP, IsValidIPv4Address and IsValidIPv6Address tests together. (Any string that passes IsValidIP should pass either IsValidIPv4Address or IsValidIPv6Address but not both, and any string that fails IsValidIP should fail both IsValidIPv4Address and IsValidIPv6Address.) Kubernetes-commit: f999b24fad907fa6f566e088bf417e9d7b217403 --- pkg/util/validation/validation_test.go | 268 ++++++++++++++++--------- 1 file changed, 170 insertions(+), 98 deletions(-) diff --git a/pkg/util/validation/validation_test.go b/pkg/util/validation/validation_test.go index c439e0398..aeda7bf56 100644 --- a/pkg/util/validation/validation_test.go +++ b/pkg/util/validation/validation_test.go @@ -323,104 +323,176 @@ func TestIsValidLabelValue(t *testing.T) { } func TestIsValidIP(t *testing.T) { - goodValues := []string{ - "::1", - "2a00:79e0:2:0:f1c3:e797:93c1:df80", - "::", - "2001:4860:4860::8888", - "::fff:1.1.1.1", - "1.1.1.1", - "1.1.1.01", - "255.0.0.1", - "1.0.0.0", - "0.0.0.0", - } - for _, val := range goodValues { - if msgs := IsValidIP(val); len(msgs) != 0 { - t.Errorf("expected true for %q: %v", val, msgs) - } - } - - badValues := []string{ - "[2001:db8:0:1]:80", - "myhost.mydomain", - "-1.0.0.0", - "[2001:db8:0:1]", - "a", - } - for _, val := range badValues { - if msgs := IsValidIP(val); len(msgs) == 0 { - t.Errorf("expected false for %q", val) - } - } -} - -func TestIsValidIPv4Address(t *testing.T) { - goodValues := []string{ - "1.1.1.1", - "1.1.1.01", - "255.0.0.1", - "1.0.0.0", - "0.0.0.0", - } - for _, val := range goodValues { - if msgs := IsValidIPv4Address(field.NewPath(""), val); len(msgs) != 0 { - t.Errorf("expected %q to be valid IPv4 address: %v", val, msgs) - } - } - - badValues := []string{ - "[2001:db8:0:1]:80", - "myhost.mydomain", - "-1.0.0.0", - "[2001:db8:0:1]", - "a", - "2001:4860:4860::8888", - "::fff:1.1.1.1", - "::1", - "2a00:79e0:2:0:f1c3:e797:93c1:df80", - "::", - } - for _, val := range badValues { - if msgs := IsValidIPv4Address(field.NewPath(""), val); len(msgs) == 0 { - t.Errorf("expected %q to be invalid IPv4 address", val) - } - } -} - -func TestIsValidIPv6Address(t *testing.T) { - goodValues := []string{ - "2001:4860:4860::8888", - "2a00:79e0:2:0:f1c3:e797:93c1:df80", - "2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "::fff:1.1.1.1", - "::1", - "::", - } - - for _, val := range goodValues { - if msgs := IsValidIPv6Address(field.NewPath(""), val); len(msgs) != 0 { - t.Errorf("expected %q to be valid IPv6 address: %v", val, msgs) - } - } - - badValues := []string{ - "1.1.1.1", - "1.1.1.01", - "255.0.0.1", - "1.0.0.0", - "0.0.0.0", - "[2001:db8:0:1]:80", - "myhost.mydomain", - "2001:0db8:85a3:0000:0000:8a2e:0370:7334:2001:0db8:85a3:0000:0000:8a2e:0370:7334", - "-1.0.0.0", - "[2001:db8:0:1]", - "a", - } - for _, val := range badValues { - if msgs := IsValidIPv6Address(field.NewPath(""), val); len(msgs) == 0 { - t.Errorf("expected %q to be invalid IPv6 address", val) - } + for _, tc := range []struct { + name string + in string + family int + err string + }{ + // GOOD VALUES + { + name: "ipv4", + in: "1.2.3.4", + family: 4, + }, + { + name: "ipv4, all zeros", + in: "0.0.0.0", + family: 4, + }, + { + name: "ipv4, max", + in: "255.255.255.255", + family: 4, + }, + { + name: "ipv6", + in: "1234::abcd", + family: 6, + }, + { + name: "ipv6, all zeros, collapsed", + in: "::", + family: 6, + }, + { + name: "ipv6, max", + in: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + family: 6, + }, + + // GOOD, THOUGH NON-CANONICAL, VALUES + { + name: "ipv6, all zeros, expanded (non-canonical)", + in: "0:0:0:0:0:0:0:0", + family: 6, + }, + { + name: "ipv6, leading 0s (non-canonical)", + in: "0001:002:03:4::", + family: 6, + }, + { + name: "ipv6, capital letters (non-canonical)", + in: "1234::ABCD", + family: 6, + }, + + // BAD VALUES WE CURRENTLY CONSIDER GOOD + { + name: "ipv4 with leading 0s", + in: "1.1.1.01", + family: 4, + }, + { + name: "ipv4-in-ipv6 value", + in: "::ffff:1.1.1.1", + family: 4, + }, + + // BAD VALUES + { + name: "empty string", + in: "", + err: "must be a valid IP address", + }, + { + name: "junk", + in: "aaaaaaa", + err: "must be a valid IP address", + }, + { + name: "domain name", + in: "myhost.mydomain", + err: "must be a valid IP address", + }, + { + name: "cidr", + in: "1.2.3.0/24", + err: "must be a valid IP address", + }, + { + name: "ipv4 with out-of-range octets", + in: "1.2.3.400", + err: "must be a valid IP address", + }, + { + name: "ipv4 with negative octets", + in: "-1.0.0.0", + err: "must be a valid IP address", + }, + { + name: "ipv6 with out-of-range segment", + in: "2001:db8::10005", + err: "must be a valid IP address", + }, + { + name: "ipv4:port", + in: "1.2.3.4:80", + err: "must be a valid IP address", + }, + { + name: "ipv6 with brackets", + in: "[2001:db8::1]", + err: "must be a valid IP address", + }, + { + name: "[ipv6]:port", + in: "[2001:db8::1]:80", + err: "must be a valid IP address", + }, + { + name: "host:port", + in: "example.com:80", + err: "must be a valid IP address", + }, + { + name: "ipv6 with zone", + in: "1234::abcd%eth0", + err: "must be a valid IP address", + }, + { + name: "ipv4 with zone", + in: "169.254.0.0%eth0", + err: "must be a valid IP address", + }, + } { + t.Run(tc.name, func(t *testing.T) { + msgs := IsValidIP(tc.in) + if tc.err == "" { + if len(msgs) != 0 { + t.Errorf("expected %q to be valid but got: %v", tc.in, msgs) + } + } else { + if len(msgs) != 1 { + t.Errorf("expected %q to have 1 error but got: %v", tc.in, msgs) + } else if !strings.Contains(msgs[0], tc.err) { + t.Errorf("expected error for %q to contain %q but got: %q", tc.in, tc.err, msgs[0]) + } + } + + errs := IsValidIPv4Address(field.NewPath(""), tc.in) + if tc.family == 4 { + if len(errs) != 0 { + t.Errorf("expected %q to pass IsValidIPv4Address but got: %v", tc.in, errs) + } + } else { + if len(errs) == 0 { + t.Errorf("expected %q to fail IsValidIPv4Address", tc.in) + } + } + + errs = IsValidIPv6Address(field.NewPath(""), tc.in) + if tc.family == 6 { + if len(errs) != 0 { + t.Errorf("expected %q to pass IsValidIPv6Address but got: %v", tc.in, errs) + } + } else { + if len(errs) == 0 { + t.Errorf("expected %q to fail IsValidIPv6Address", tc.in) + } + } + }) } }