package util import ( "net/netip" "slices" "strings" "testing" ) func TestParseNetPrefixes(t *testing.T) { tests := []struct { name string list []string want []string }{ {"nil list", nil, []string{}}, {"IPv4 address", []string{"192.0.2.1"}, []string{"192.0.2.1/32"}}, {"IPv6 address", []string{"2001:db8::1"}, []string{"2001:db8::1/128"}}, {"IPv4-mapped address is unmapped", []string{"::ffff:192.0.2.1"}, []string{"192.0.2.1/32"}}, {"CIDR range", []string{"10.0.0.0/8"}, []string{"10.0.0.0/8"}}, {"CIDR range is masked", []string{"10.1.2.3/8"}, []string{"10.0.0.0/8"}}, {"IPv6 CIDR range is masked", []string{"2001:db8::1/32"}, []string{"2001:db8::/32"}}, { "trimmed, blanks skipped, order kept", []string{" 127.0.0.1 ", "", " ", "\t10.0.0.0/8\n", "::1"}, []string{"127.0.0.1/32", "10.0.0.0/8", "::1/128"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := ParseNetPrefixes(tt.list) if err != nil { t.Fatalf("ParseNetPrefixes(%q): %v", tt.list, err) } if got == nil { t.Fatalf("ParseNetPrefixes(%q) = nil; want an empty list", tt.list) } gotStrings := []string{} for _, p := range got { gotStrings = append(gotStrings, p.String()) } if !slices.Equal(gotStrings, tt.want) { t.Errorf( "ParseNetPrefixes(%q) = %v; want %v", tt.list, gotStrings, tt.want, ) } }) } } // The prefixes hold the addresses they should: a single address only itself, // a range everything in it. func TestParseNetPrefixesContains(t *testing.T) { got, err := ParseNetPrefixes([]string{"192.0.2.1", "10.0.0.0/8"}) if err != nil { t.Fatal(err) } tests := []struct { addr string want bool }{ {"192.0.2.1", true}, {"192.0.2.2", false}, {"10.255.0.1", true}, {"11.0.0.1", false}, } for _, tt := range tests { addr := netip.MustParseAddr(tt.addr) contained := slices.ContainsFunc(got, func(p netip.Prefix) bool { return p.Contains(addr) }) if contained != tt.want { t.Errorf("%s contained = %v; want %v", tt.addr, contained, tt.want) } } } // The first entry that can't be parsed is an error naming it, and no // prefixes are returned. func TestParseNetPrefixesErrors(t *testing.T) { for _, entry := range []string{ "not-an-ip", "192.0.2.256", "10.0.0.0/33", "10.0.0.0/x", "2001:db8::/129", "192.0.2.1:80", } { got, err := ParseNetPrefixes([]string{"127.0.0.1", entry}) if err == nil || !strings.Contains(err.Error(), entry) { t.Errorf( "ParseNetPrefixes(%q) error = %v; want one naming it", entry, err, ) } if got != nil { t.Errorf("ParseNetPrefixes(%q) = %v; want nil", entry, got) } } }