From f999b24fad907fa6f566e088bf417e9d7b217403 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.) --- .../pkg/util/validation/validation_test.go | 258 +++++++++++------- 1 file changed, 165 insertions(+), 93 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/validation/validation_test.go b/staging/src/k8s.io/apimachinery/pkg/util/validation/validation_test.go index c439e0398c2..aeda7bf5662 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/validation/validation_test.go +++ b/staging/src/k8s.io/apimachinery/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) - } - } + 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, + }, - 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) - } - } -} + // 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, + }, -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) - } - } + // 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, + }, - 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) - } - } -} + // 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]) + } + } -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", - "::", - } + 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) + } + } - 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) - } + 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) + } + } + }) } }