api/t/net: test EndpointIPAMConfig.Validate()

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
This commit is contained in:
Albin Kerouanton 2023-09-15 13:40:30 +02:00
parent 3092b261e2
commit acf825def2
No known key found for this signature in database
GPG key ID: 630B8E1DCBDB1864

View file

@ -0,0 +1,188 @@
package network
import (
"net"
"testing"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
type subnetStub struct {
static bool
contains map[string]bool
}
func (stub subnetStub) IsStatic() bool {
return stub.static
}
func (stub subnetStub) Contains(addr net.IP) bool {
v, ok := stub.contains[addr.String()]
return ok && v
}
func TestEndpointIPAMConfigWithOutOfRangeAddrs(t *testing.T) {
testcases := []struct {
name string
ipamConfig *EndpointIPAMConfig
v4Subnets []NetworkSubnet
v6Subnets []NetworkSubnet
expectedErrors []string
}{
{
name: "valid config",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "192.168.100.10",
IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"},
},
v4Subnets: []NetworkSubnet{
subnetStub{static: true, contains: map[string]bool{"192.168.100.10": true}},
},
v6Subnets: []NetworkSubnet{
subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": true}},
},
},
{
name: "static addresses out of range",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "192.168.100.10",
IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
},
v4Subnets: []NetworkSubnet{
subnetStub{static: true, contains: map[string]bool{"192.168.100.10": false}},
},
v6Subnets: []NetworkSubnet{
subnetStub{static: true, contains: map[string]bool{"2a01:d2:af:420b:25c1:1816:bb33:855c": false}},
},
expectedErrors: []string{
"no configured subnet or ip-range contain the IP address 192.168.100.10",
"no configured subnet or ip-range contain the IP address 2a01:d2:af:420b:25c1:1816:bb33:855c",
},
},
{
name: "static addresses with dynamic network subnets",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "192.168.100.10",
IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
},
v4Subnets: []NetworkSubnet{
subnetStub{static: false},
},
v6Subnets: []NetworkSubnet{
subnetStub{static: false},
},
expectedErrors: []string{
"user specified IP address is supported only when connecting to networks with user configured subnets",
"user specified IP address is supported only when connecting to networks with user configured subnets",
},
},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
err := tc.ipamConfig.IsInRange(tc.v4Subnets, tc.v6Subnets)
if tc.expectedErrors == nil {
assert.NilError(t, err)
return
}
if _, ok := err.(interface{ Unwrap() []error }); !ok {
t.Fatal("returned error isn't a multierror")
}
errs := err.(interface{ Unwrap() []error }).Unwrap()
assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs)
for _, expected := range tc.expectedErrors {
assert.Check(t, is.ErrorContains(err, expected))
}
})
}
}
func TestEndpointIPAMConfigWithInvalidConfig(t *testing.T) {
testcases := []struct {
name string
ipamConfig *EndpointIPAMConfig
expectedErrors []string
}{
{
name: "valid config",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "192.168.100.10",
IPv6Address: "2a01:d2:af:420b:25c1:1816:bb33:855c",
LinkLocalIPs: []string{"169.254.169.254", "fe80::42:a8ff:fe33:6230"},
},
},
{
name: "invalid IP addresses",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "foo",
IPv6Address: "bar",
LinkLocalIPs: []string{"baz", "foobar"},
},
expectedErrors: []string{
"invalid IPv4 address: foo",
"invalid IPv6 address: bar",
"invalid link-local IP address: baz",
"invalid link-local IP address: foobar",
},
},
{
name: "ipv6 address with a zone",
ipamConfig: &EndpointIPAMConfig{IPv6Address: "fe80::1cc0:3e8c:119f:c2e1%ens18"},
expectedErrors: []string{
"invalid IPv6 address: fe80::1cc0:3e8c:119f:c2e1%ens18",
},
},
{
name: "unspecified address is invalid",
ipamConfig: &EndpointIPAMConfig{
IPv4Address: "0.0.0.0",
IPv6Address: "::",
LinkLocalIPs: []string{"0.0.0.0", "::"},
},
expectedErrors: []string{
"invalid IPv4 address: 0.0.0.0",
"invalid IPv6 address: ::",
"invalid link-local IP address: 0.0.0.0",
"invalid link-local IP address: ::",
},
},
{
name: "empty link-local",
ipamConfig: &EndpointIPAMConfig{
LinkLocalIPs: []string{""},
},
expectedErrors: []string{"invalid link-local IP address:"},
},
}
for _, tc := range testcases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
err := tc.ipamConfig.Validate()
if tc.expectedErrors == nil {
assert.NilError(t, err)
return
}
if _, ok := err.(interface{ Unwrap() []error }); !ok {
t.Fatal("returned error isn't a multierror")
}
errs := err.(interface{ Unwrap() []error }).Unwrap()
assert.Check(t, len(errs) == len(tc.expectedErrors), "errs: %+v", errs)
for _, expected := range tc.expectedErrors {
assert.Check(t, is.ErrorContains(err, expected))
}
})
}
}