Files
user-system/internal/pkg/ip/ip_test.go

244 lines
6.0 KiB
Go
Raw Normal View History

package ip
import (
"net"
"testing"
"github.com/stretchr/testify/require"
)
func TestNormalizeIP(t *testing.T) {
tests := []struct {
name string
ip string
want string
}{
{"plain_ip", "192.168.1.1", "192.168.1.1"},
{"with_port", "192.168.1.1:8080", "192.168.1.1"},
{"with_spaces", " 192.168.1.1 ", "192.168.1.1"},
{"ipv6", "::1", "::1"},
{"ipv6_with_port", "[::1]:8080", "::1"},
{"empty", "", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := normalizeIP(tt.ip)
require.Equal(t, tt.want, got)
})
}
}
func TestIsPrivateIP(t *testing.T) {
tests := []struct {
name string
ip string
want bool
}{
{"private_10.x", "10.0.0.1", true},
{"private_172.16.x", "172.16.0.1", true},
{"private_172.31.x", "172.31.0.1", true},
{"private_192.168.x", "192.168.1.1", true},
{"private_loopback", "127.0.0.1", true},
{"private_ipv6_loopback", "::1", true},
{"public_ip", "8.8.8.8", false},
{"public_ip2", "1.1.1.1", false},
{"invalid_ip", "invalid", false},
{"empty_ip", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := isPrivateIP(tt.ip)
require.Equal(t, tt.want, got)
})
}
}
func TestCompileIPRules(t *testing.T) {
tests := []struct {
name string
patterns []string
wantCIDRs int
wantIPs int
wantPatterns int
}{
{
name: "empty",
patterns: []string{},
wantCIDRs: 0,
wantIPs: 0,
wantPatterns: 0,
},
{
name: "single_ip",
patterns: []string{"192.168.1.1"},
wantCIDRs: 0,
wantIPs: 1,
wantPatterns: 1,
},
{
name: "single_cidr",
patterns: []string{"192.168.0.0/24"},
wantCIDRs: 1,
wantIPs: 0,
wantPatterns: 1,
},
{
name: "mixed",
patterns: []string{"192.168.1.1", "10.0.0.0/8"},
wantCIDRs: 1,
wantIPs: 1,
wantPatterns: 2,
},
{
name: "with_invalid",
patterns: []string{"192.168.1.1", "invalid", "10.0.0.0/8"},
wantCIDRs: 1,
wantIPs: 1,
wantPatterns: 3,
},
{
name: "with_empty_and_spaces",
patterns: []string{"", " ", "192.168.1.1"},
wantCIDRs: 0,
wantIPs: 1,
wantPatterns: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rules := CompileIPRules(tt.patterns)
require.Equal(t, tt.wantCIDRs, len(rules.CIDRs))
require.Equal(t, tt.wantIPs, len(rules.IPs))
require.Equal(t, tt.wantPatterns, rules.PatternCount)
})
}
}
func TestMatchesCompiledRules(t *testing.T) {
rules := CompileIPRules([]string{"192.168.1.1", "10.0.0.0/8"})
tests := []struct {
name string
ip string
want bool
}{
{"match_ip", "192.168.1.1", true},
{"match_cidr", "10.0.1.1", true},
{"no_match", "8.8.8.8", false},
{"invalid", "invalid", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ip := net.ParseIP(tt.ip)
got := matchesCompiledRules(ip, rules)
require.Equal(t, tt.want, got)
})
}
}
func TestMatchesCompiledRules_NilCases(t *testing.T) {
rules := CompileIPRules([]string{"192.168.1.1"})
// nil IP
require.False(t, matchesCompiledRules(nil, rules))
// nil rules
validIP := net.ParseIP("192.168.1.1")
require.False(t, matchesCompiledRules(validIP, nil))
}
func TestMatchesPattern(t *testing.T) {
tests := []struct {
name string
client string
pattern string
want bool
}{
{"ip_match", "192.168.1.1", "192.168.1.1", true},
{"ip_no_match", "192.168.1.1", "192.168.1.2", false},
{"cidr_match", "192.168.1.50", "192.168.1.0/24", true},
{"cidr_no_match", "192.168.2.1", "192.168.1.0/24", false},
{"invalid_client", "invalid", "192.168.1.0/24", false},
{"invalid_pattern", "192.168.1.1", "invalid", false},
{"invalid_cidr", "192.168.1.1", "192.168.1/24", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := MatchesPattern(tt.client, tt.pattern)
require.Equal(t, tt.want, got)
})
}
}
func TestMatchesAnyPattern(t *testing.T) {
patterns := []string{"192.168.1.1", "10.0.0.0/8"}
require.True(t, MatchesAnyPattern("192.168.1.1", patterns))
require.True(t, MatchesAnyPattern("10.0.1.1", patterns))
require.False(t, MatchesAnyPattern("8.8.8.8", patterns))
require.False(t, MatchesAnyPattern("8.8.8.8", []string{}))
}
func TestCheckIPRestriction(t *testing.T) {
tests := []struct {
name string
clientIP string
whitelist []string
blacklist []string
wantAllow bool
}{
{"no_restrictions", "192.168.1.1", nil, nil, true},
{"whitelist_match", "192.168.1.1", []string{"192.168.1.0/24"}, nil, true},
{"whitelist_no_match", "192.168.1.1", []string{"10.0.0.0/8"}, nil, false},
{"blacklist_match", "192.168.1.1", nil, []string{"192.168.1.0/24"}, false},
{"blacklist_no_match", "192.168.1.1", nil, []string{"10.0.0.0/8"}, true},
{"blacklist_priority", "192.168.1.1", []string{"0.0.0.0/0"}, []string{"192.168.1.0/24"}, false},
{"empty_ip", "", []string{"192.168.1.0/24"}, nil, false},
{"invalid_ip", "invalid", []string{"192.168.1.0/24"}, nil, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
allow, _ := CheckIPRestriction(tt.clientIP, tt.whitelist, tt.blacklist)
require.Equal(t, tt.wantAllow, allow)
})
}
}
func TestValidateIPPattern(t *testing.T) {
tests := []struct {
name string
pattern string
want bool
}{
{"valid_ip", "192.168.1.1", true},
{"valid_ipv6", "::1", true},
{"valid_cidr", "192.168.0.0/24", true},
{"invalid", "not-an-ip", false},
{"empty", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateIPPattern(tt.pattern)
require.Equal(t, tt.want, got)
})
}
}
func TestValidateIPPatterns(t *testing.T) {
patterns := []string{"192.168.1.1", "invalid", "192.168.0.0/24", "not-an-ip"}
invalid := ValidateIPPatterns(patterns)
require.Equal(t, []string{"invalid", "not-an-ip"}, invalid)
// all valid
validPatterns := []string{"192.168.1.1", "192.168.0.0/24"}
invalid = ValidateIPPatterns(validPatterns)
require.Empty(t, invalid)
}