Files
kubernetes/pkg/api/servicecidr/servicecidr_test.go
2024-06-30 09:48:46 +00:00

732 lines
23 KiB
Go

/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package servicecidr
import (
"net/netip"
"reflect"
"sort"
"testing"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
networkinglisters "k8s.io/client-go/listers/networking/v1beta1"
"k8s.io/client-go/tools/cache"
netutils "k8s.io/utils/net"
)
func newServiceCIDR(name, primary, secondary string) *networkingv1beta1.ServiceCIDR {
serviceCIDR := &networkingv1beta1.ServiceCIDR{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: networkingv1beta1.ServiceCIDRSpec{},
}
serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, primary)
if secondary != "" {
serviceCIDR.Spec.CIDRs = append(serviceCIDR.Spec.CIDRs, secondary)
}
return serviceCIDR
}
func TestOverlapsPrefix(t *testing.T) {
tests := []struct {
name string
serviceCIDRs []*networkingv1beta1.ServiceCIDR
prefix netip.Prefix
want []string
}{
{
name: "only one ServiceCIDR and IPv4 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/26"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and same IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/24"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and larger IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/16"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and non contained IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("192.168.0.0/24"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv6 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/112"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and same IPv6 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/96"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv6 larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/64"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv6 prefix out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db2::/112"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv4 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/24"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two overlapping ServiceCIDR and IPv4 prefix only contained in one",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/18"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv4 larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/8"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv4 prefix not contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("192.168.0.0/24"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv6 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/96"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv6 prefix contained in one",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/72"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and aprefix larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/52"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and prefix out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db2::/64"),
want: []string{},
},
{
name: "multiple ServiceCIDR match with overlap contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("kubernetes2", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/28"),
want: []string{"kubernetes", "kubernetes2", "secondary"},
},
{
name: "multiple ServiceCIDR match with overlap contains",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("kubernetes2", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/8"),
want: []string{"kubernetes", "kubernetes2", "secondary"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
for _, serviceCIDR := range tt.serviceCIDRs {
err := indexer.Add(serviceCIDR)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
}
lister := networkinglisters.NewServiceCIDRLister(indexer)
got := []string{}
for _, serviceCIDR := range OverlapsPrefix(lister, tt.prefix) {
got = append(got, serviceCIDR.Name)
}
// sort slices to make the order predictable and avoid flakiness
sort.Strings(got)
sort.Strings(tt.want)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("OverlapsAddress() = %v, want %v", got, tt.want)
}
})
}
}
func TestContainsPrefix(t *testing.T) {
tests := []struct {
name string
serviceCIDRs []*networkingv1beta1.ServiceCIDR
prefix netip.Prefix
want []string
}{
{
name: "only one ServiceCIDR and IPv4 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/26"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and same IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/24"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and larger IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("10.0.0.0/16"),
want: []string{},
},
{
name: "only one ServiceCIDR and non containerd IPv4 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("192.168.0.0/24"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv6 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/112"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and same IPv6 prefix",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/96"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv6 larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db8::/64"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv6 prefix out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
prefix: netip.MustParsePrefix("2001:db2::/112"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv4 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/24"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv4 prefix only contained in one",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/18"),
want: []string{"secondary"},
},
{
name: "two ServiceCIDR and IPv4 larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/8"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv4 prefix not contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("192.168.0.0/24"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv6 prefix contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/96"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv6 prefix contained in one",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/72"),
want: []string{"secondary"},
},
{
name: "two ServiceCIDR and aprefix larger",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db8::/52"),
want: []string{},
},
{
name: "two ServiceCIDR and prefix out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("2001:db2::/64"),
want: []string{},
},
{
name: "multiple ServiceCIDR match with overlap",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("kubernetes2", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
prefix: netip.MustParsePrefix("10.0.0.0/28"),
want: []string{"kubernetes", "kubernetes2", "secondary"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
for _, serviceCIDR := range tt.serviceCIDRs {
err := indexer.Add(serviceCIDR)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
}
lister := networkinglisters.NewServiceCIDRLister(indexer)
got := []string{}
for _, serviceCIDR := range ContainsPrefix(lister, tt.prefix) {
got = append(got, serviceCIDR.Name)
}
// sort slices to make the order predictable and avoid flakiness
sort.Strings(got)
sort.Strings(tt.want)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ContainsAddress() = %v, want %v", got, tt.want)
}
})
}
}
func TestContainsAddress(t *testing.T) {
tests := []struct {
name string
serviceCIDRs []*networkingv1beta1.ServiceCIDR
address netip.Addr
want []string
}{
{
name: "only one ServiceCIDR and IPv4 address contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("10.0.0.1"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv4 address broadcast",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("10.0.0.255"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv4 address base",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("10.0.0.0"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv4 address out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("192.0.0.1"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv6 address contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("2001:db8::2:3"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv6 address broadcast",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("2001:db8::ffff:ffff"),
want: []string{"kubernetes"},
},
{
name: "only one ServiceCIDR and IPv6 address base",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("2001:db8::"),
want: []string{},
},
{
name: "only one ServiceCIDR and IPv6 address out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
},
address: netip.MustParseAddr("2002:1:2:3::2"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv4 address contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("10.0.0.1"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and IPv4 address broadcast",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("10.0.0.255"),
want: []string{"secondary"},
},
{
name: "two ServiceCIDR and IPv4 address base",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("10.0.0.0"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv4 address out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("192.0.0.1"),
want: []string{},
},
{
name: "two ServiceCIDR and IPv6 address contained",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("2001:db8::2:3"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and address broadcast",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("2001:db8::ffff:ffff"),
want: []string{"kubernetes", "secondary"},
},
{
name: "two ServiceCIDR and address base",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("2001:db8::"),
want: []string{},
},
{
name: "two ServiceCIDR and address out of range",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("2002:1:2:3::2"),
want: []string{},
},
{
name: "multiple ServiceCIDR match with overlap",
serviceCIDRs: []*networkingv1beta1.ServiceCIDR{
newServiceCIDR("kubernetes", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("kubernetes2", "10.0.0.0/24", "2001:db8::/96"),
newServiceCIDR("secondary", "10.0.0.0/16", "2001:db8::/64"),
},
address: netip.MustParseAddr("10.0.0.2"),
want: []string{"kubernetes", "kubernetes2", "secondary"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
for _, serviceCIDR := range tt.serviceCIDRs {
err := indexer.Add(serviceCIDR)
if err != nil {
t.Fatalf("unexpected error %v", err)
}
}
lister := networkinglisters.NewServiceCIDRLister(indexer)
got := []string{}
for _, serviceCIDR := range ContainsAddress(lister, tt.address) {
got = append(got, serviceCIDR.Name)
}
// sort slices to make the order predictable and avoid flakiness
sort.Strings(got)
sort.Strings(tt.want)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("ContainsAddress() = %v, want %v", got, tt.want)
}
})
}
}
func Test_PrefixContainIP(t *testing.T) {
tests := []struct {
name string
prefix netip.Prefix
ip netip.Addr
want bool
}{
{
name: "IPv4 contains",
prefix: netip.MustParsePrefix("192.168.0.0/24"),
ip: netip.MustParseAddr("192.168.0.1"),
want: true,
},
{
name: "IPv4 network address",
prefix: netip.MustParsePrefix("192.168.0.0/24"),
ip: netip.MustParseAddr("192.168.0.0"),
},
{
name: "IPv4 broadcast address",
prefix: netip.MustParsePrefix("192.168.0.0/24"),
ip: netip.MustParseAddr("192.168.0.255"),
},
{
name: "IPv4 does not contain",
prefix: netip.MustParsePrefix("192.168.0.0/24"),
ip: netip.MustParseAddr("192.168.1.2"),
},
{
name: "IPv6 contains",
prefix: netip.MustParsePrefix("2001:db2::/96"),
ip: netip.MustParseAddr("2001:db2::1"),
want: true,
},
{
name: "IPv6 network address",
prefix: netip.MustParsePrefix("2001:db2::/96"),
ip: netip.MustParseAddr("2001:db2::"),
},
{
name: "IPv6 broadcast address",
prefix: netip.MustParsePrefix("2001:db2::/96"),
ip: netip.MustParseAddr("2001:db2::ffff:ffff"),
want: true,
},
{
name: "IPv6 does not contain",
prefix: netip.MustParsePrefix("2001:db2::/96"),
ip: netip.MustParseAddr("2001:db2:1:2:3::1"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := PrefixContainsIP(tt.prefix, tt.ip); got != tt.want {
t.Errorf("prefixContainIP() = %v, want %v", got, tt.want)
}
})
}
}
func TestIPToAddr(t *testing.T) {
tests := []struct {
name string
ip string
want netip.Addr
}{
{
name: "IPv4",
ip: "192.168.2.2",
want: netip.MustParseAddr("192.168.2.2"),
},
{
name: "IPv6",
ip: "2001:db8::2",
want: netip.MustParseAddr("2001:db8::2"),
},
{
name: "IPv4 in IPv6",
ip: "::ffff:192.168.0.1",
want: netip.MustParseAddr("192.168.0.1"),
},
{
name: "invalid",
ip: "invalid_ip",
want: netip.Addr{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ip := netutils.ParseIPSloppy(tt.ip)
if got := IPToAddr(ip); !reflect.DeepEqual(got, tt.want) {
t.Errorf("IPToAddr() = %v, want %v", got, tt.want)
}
})
}
}
func TestBroadcastAddress(t *testing.T) {
tests := []struct {
name string
subnet netip.Prefix
want netip.Addr
wantErr bool
}{
{
name: "emty subnet",
wantErr: true,
},
{
name: "IPv4 even mask",
subnet: netip.MustParsePrefix("192.168.0.0/24"),
want: netip.MustParseAddr("192.168.0.255"),
},
{
name: "IPv4 odd mask",
subnet: netip.MustParsePrefix("192.168.0.0/23"),
want: netip.MustParseAddr("192.168.1.255"),
},
{
name: "IPv6 even mask",
subnet: netip.MustParsePrefix("fd00:1:2:3::/64"),
want: netip.MustParseAddr("fd00:1:2:3:ffff:ffff:ffff:ffff"),
},
{
name: "IPv6 odd mask",
subnet: netip.MustParsePrefix("fd00:1:2:3::/57"),
want: netip.MustParseAddr("fd00:1:2:007f:ffff:ffff:ffff:ffff"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := broadcastAddress(tt.subnet)
if (err != nil) != tt.wantErr {
t.Errorf("BroadcastAddress() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("BroadcastAddress() = %v, want %v", got, tt.want)
}
})
}
}