mirror of https://github.com/docker/cli.git
opts: ValidateIPAddress: improve error, godoc, and tests
- document accepted values - add test-coverage for the function's behavior (including whitespace handling), and use sub-tests. - improve error-message to use uppercase for "IP", and to use a common prefix. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
79c5d4a329
commit
b0ee27d653
|
@ -199,7 +199,7 @@ func TestUpdateDNSConfig(t *testing.T) {
|
||||||
// IPv6
|
// IPv6
|
||||||
flags.Set("dns-add", "2001:db8:abc8::1")
|
flags.Set("dns-add", "2001:db8:abc8::1")
|
||||||
// Invalid dns record
|
// Invalid dns record
|
||||||
assert.ErrorContains(t, flags.Set("dns-add", "x.y.z.w"), "x.y.z.w is not an ip address")
|
assert.Check(t, is.ErrorContains(flags.Set("dns-add", "x.y.z.w"), "IP address is not correctly formatted: x.y.z.w"))
|
||||||
|
|
||||||
// domains with duplicates
|
// domains with duplicates
|
||||||
flags.Set("dns-search-add", "example.com")
|
flags.Set("dns-search-add", "example.com")
|
||||||
|
|
12
opts/opts.go
12
opts/opts.go
|
@ -224,13 +224,17 @@ type ValidatorFctType func(val string) (string, error)
|
||||||
// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
|
// ValidatorFctListType defines a validator function that returns a validated list of string and/or an error
|
||||||
type ValidatorFctListType func(val string) ([]string, error)
|
type ValidatorFctListType func(val string) ([]string, error)
|
||||||
|
|
||||||
// ValidateIPAddress validates an Ip address.
|
// ValidateIPAddress validates if the given value is a correctly formatted
|
||||||
|
// IP address, and returns the value in normalized form. Leading and trailing
|
||||||
|
// whitespace is allowed, but it does not allow IPv6 addresses surrounded by
|
||||||
|
// square brackets ("[::1]").
|
||||||
|
//
|
||||||
|
// Refer to [net.ParseIP] for accepted formats.
|
||||||
func ValidateIPAddress(val string) (string, error) {
|
func ValidateIPAddress(val string) (string, error) {
|
||||||
ip := net.ParseIP(strings.TrimSpace(val))
|
if ip := net.ParseIP(strings.TrimSpace(val)); ip != nil {
|
||||||
if ip != nil {
|
|
||||||
return ip.String(), nil
|
return ip.String(), nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("%s is not an ip address", val)
|
return "", fmt.Errorf("IP address is not correctly formatted: %s", val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateMACAddress validates a MAC address.
|
// ValidateMACAddress validates a MAC address.
|
||||||
|
|
|
@ -6,27 +6,79 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
|
is "gotest.tools/v3/assert/cmp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateIPAddress(t *testing.T) {
|
func TestValidateIPAddress(t *testing.T) {
|
||||||
if ret, err := ValidateIPAddress(`1.2.3.4`); err != nil || ret == "" {
|
tests := []struct {
|
||||||
t.Fatalf("ValidateIPAddress(`1.2.3.4`) got %s %s", ret, err)
|
doc string
|
||||||
|
input string
|
||||||
|
expectedOut string
|
||||||
|
expectedErr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
doc: "IPv4 loopback",
|
||||||
|
input: `127.0.0.1`,
|
||||||
|
expectedOut: `127.0.0.1`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv4 loopback with whitespace",
|
||||||
|
input: ` 127.0.0.1 `,
|
||||||
|
expectedOut: `127.0.0.1`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 loopback long form",
|
||||||
|
input: `0:0:0:0:0:0:0:1`,
|
||||||
|
expectedOut: `::1`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 loopback",
|
||||||
|
input: `::1`,
|
||||||
|
expectedOut: `::1`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 loopback with whitespace",
|
||||||
|
input: ` ::1 `,
|
||||||
|
expectedOut: `::1`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 lowercase",
|
||||||
|
input: `2001:db8::68`,
|
||||||
|
expectedOut: `2001:db8::68`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 uppercase",
|
||||||
|
input: `2001:DB8::68`,
|
||||||
|
expectedOut: `2001:db8::68`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv6 with brackets",
|
||||||
|
input: `[::1]`,
|
||||||
|
expectedErr: `IP address is not correctly formatted: [::1]`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "IPv4 partial",
|
||||||
|
input: `127`,
|
||||||
|
expectedErr: `IP address is not correctly formatted: 127`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
doc: "random invalid string",
|
||||||
|
input: `random invalid string`,
|
||||||
|
expectedErr: `IP address is not correctly formatted: random invalid string`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if ret, err := ValidateIPAddress(`127.0.0.1`); err != nil || ret == "" {
|
for _, tc := range tests {
|
||||||
t.Fatalf("ValidateIPAddress(`127.0.0.1`) got %s %s", ret, err)
|
tc := tc
|
||||||
|
t.Run(tc.input, func(t *testing.T) {
|
||||||
|
actualOut, actualErr := ValidateIPAddress(tc.input)
|
||||||
|
assert.Check(t, is.Equal(tc.expectedOut, actualOut))
|
||||||
|
if tc.expectedErr == "" {
|
||||||
|
assert.Check(t, actualErr)
|
||||||
|
} else {
|
||||||
|
assert.Check(t, is.Error(actualErr, tc.expectedErr))
|
||||||
}
|
}
|
||||||
|
})
|
||||||
if ret, err := ValidateIPAddress(`::1`); err != nil || ret == "" {
|
|
||||||
t.Fatalf("ValidateIPAddress(`::1`) got %s %s", ret, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret, err := ValidateIPAddress(`127`); err == nil || ret != "" {
|
|
||||||
t.Fatalf("ValidateIPAddress(`127`) got %s %s", ret, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ret, err := ValidateIPAddress(`random invalid string`); err == nil || ret != "" {
|
|
||||||
t.Fatalf("ValidateIPAddress(`random invalid string`) got %s %s", ret, err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue