Initial commit.

This commit is contained in:
2025-11-28 02:50:25 +00:00
commit 22552aec99
41 changed files with 10626 additions and 0 deletions
+436
View File
@@ -0,0 +1,436 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestValidateDomain(t *testing.T) {
tests := []struct {
domain string
valid bool
}{
{"example.com", true},
{"sub.example.com", true},
{"my-app.example.com", true},
{"localhost", true},
{"a.b.c.d.example.com", true},
{"example123.com", true},
{"", false},
{"-example.com", false},
{"example-.com", false},
{"example.c", false}, // TLD too short
{"example", false}, // No TLD
{".example.com", false},
{"example..com", false},
}
for _, tt := range tests {
t.Run(tt.domain, func(t *testing.T) {
result := ValidateDomain(tt.domain)
assert.Equal(t, tt.valid, result, "domain: %s", tt.domain)
})
}
}
func TestValidateIP(t *testing.T) {
tests := []struct {
ip string
valid bool
}{
// Valid IPv4
{"127.0.0.1", true},
{"192.168.1.1", true},
{"0.0.0.0", true},
{"255.255.255.255", true},
// Valid IPv6
{"::1", true},
{"2001:db8::1", true},
{"fe80::1", true},
{"::ffff:192.168.1.1", true},
// Invalid
{"", false},
{"256.0.0.1", false},
{"192.168.1", false},
{"not-an-ip", false},
{"192.168.1.1.1", false},
}
for _, tt := range tests {
t.Run(tt.ip, func(t *testing.T) {
result := ValidateIP(tt.ip)
assert.Equal(t, tt.valid, result, "ip: %s", tt.ip)
})
}
}
func TestValidateAlias(t *testing.T) {
tests := []struct {
alias string
valid bool
}{
{"my-alias", true},
{"myalias", true},
{"my_alias", true},
{"alias123", true},
{"a", true},
{"a-b_c-d", true},
{"", false},
{"-startswithdash", false},
{"_startswithunderscore", false},
{"has spaces", false},
{"has.dot", false},
}
for _, tt := range tests {
t.Run(tt.alias, func(t *testing.T) {
result := ValidateAlias(tt.alias)
assert.Equal(t, tt.valid, result, "alias: %s", tt.alias)
})
}
}
func TestIsBlockedDomain(t *testing.T) {
tests := []struct {
domain string
blocked bool
}{
// Blocked domains
{"apple.com", true},
{"icloud.com", true},
{"sub.apple.com", true},
{"deep.sub.icloud.com", true},
{"APPLE.COM", true}, // Case insensitive
// Allowed domains
{"example.com", false},
{"myapp.com", false},
{"applestore.com", false}, // Not a subdomain
{"notapple.com", false},
}
for _, tt := range tests {
t.Run(tt.domain, func(t *testing.T) {
result := IsBlockedDomain(tt.domain)
assert.Equal(t, tt.blocked, result, "domain: %s", tt.domain)
})
}
}
func TestGetBlockedDomains(t *testing.T) {
domains := GetBlockedDomains()
assert.NotEmpty(t, domains)
assert.Contains(t, domains, "apple.com")
assert.Contains(t, domains, "icloud.com")
}
func TestValidateConfig(t *testing.T) {
t.Run("valid config", func(t *testing.T) {
cfg := &Config{
Settings: Settings{
AutoApply: true,
FlushMethod: FlushMethodAuto,
},
Groups: []Group{
{
Name: "development",
Hosts: []Host{
{Domain: "example.com", IP: "127.0.0.1", Alias: "example", Enabled: true},
},
},
},
Presets: []Preset{
{Name: "local", Enable: []string{"example"}, Disable: []string{}},
},
}
err := ValidateConfig(cfg)
assert.NoError(t, err)
})
t.Run("nil config", func(t *testing.T) {
err := ValidateConfig(nil)
assert.Error(t, err)
})
t.Run("invalid flush method", func(t *testing.T) {
cfg := &Config{
Settings: Settings{FlushMethod: "invalid"},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("empty group name", func(t *testing.T) {
cfg := &Config{
Groups: []Group{{Name: "", Hosts: []Host{}}},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("invalid domain", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "invalid", IP: "127.0.0.1", Alias: "test", Enabled: true},
},
},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("blocked domain", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "apple.com", IP: "127.0.0.1", Alias: "test", Enabled: true},
},
},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("invalid IP", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "example.com", IP: "invalid", Alias: "test", Enabled: true},
},
},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("invalid alias", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "example.com", IP: "127.0.0.1", Alias: "-invalid", Enabled: true},
},
},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("duplicate alias", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "a.com", IP: "127.0.0.1", Alias: "same", Enabled: true},
{Domain: "b.com", IP: "127.0.0.1", Alias: "same", Enabled: true},
},
},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("empty preset name", func(t *testing.T) {
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "example.com", IP: "127.0.0.1", Alias: "test", Enabled: true},
},
},
},
Presets: []Preset{
{Name: "", Enable: []string{}},
},
}
err := ValidateConfig(cfg)
assert.Error(t, err)
})
t.Run("preset with unknown alias is allowed", func(t *testing.T) {
// Unknown aliases in presets are now allowed (they're simply skipped when applied)
// This allows presets to survive when hosts are removed from the config
cfg := &Config{
Groups: []Group{
{
Name: "dev",
Hosts: []Host{
{Domain: "example.com", IP: "127.0.0.1", Alias: "test", Enabled: true},
},
},
},
Presets: []Preset{
{Name: "local", Enable: []string{"unknown"}},
},
}
err := ValidateConfig(cfg)
assert.NoError(t, err)
})
}
func TestValidationError(t *testing.T) {
err := &ValidationError{Field: "test.field", Message: "test message"}
assert.Equal(t, "test.field: test message", err.Error())
}
func TestValidateSettings(t *testing.T) {
tests := []struct {
name string
method FlushMethod
wantErr bool
}{
{"auto", FlushMethodAuto, false},
{"dscacheutil", FlushMethodDscacheutil, false},
{"killall", FlushMethodKillall, false},
{"both", FlushMethodBoth, false},
{"empty", "", false},
{"invalid", "invalid", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
settings := &Settings{FlushMethod: tt.method}
err := validateSettings(settings)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
// Matrix testing for domain validation
func TestValidateDomain_Matrix(t *testing.T) {
prefixes := []string{"", "sub.", "a.b."}
domains := []string{"example", "my-app", "test123"}
tlds := []string{".com", ".io", ".co.uk", ".dev"}
for _, prefix := range prefixes {
for _, domain := range domains {
for _, tld := range tlds {
fullDomain := prefix + domain + tld
t.Run(fullDomain, func(t *testing.T) {
result := ValidateDomain(fullDomain)
assert.True(t, result, "expected %s to be valid", fullDomain)
})
}
}
}
}
// Matrix testing for IP validation
func TestValidateIP_Matrix(t *testing.T) {
octets := []string{"0", "127", "192", "255"}
for _, o1 := range octets {
for _, o2 := range octets {
for _, o3 := range octets {
for _, o4 := range octets {
ip := o1 + "." + o2 + "." + o3 + "." + o4
t.Run(ip, func(t *testing.T) {
result := ValidateIP(ip)
assert.True(t, result, "expected %s to be valid", ip)
})
}
}
}
}
}
// Benchmark tests
func BenchmarkValidateDomain(b *testing.B) {
domains := []string{
"example.com",
"sub.example.com",
"very.long.subdomain.chain.example.com",
}
for _, domain := range domains {
b.Run(domain, func(b *testing.B) {
for i := 0; i < b.N; i++ {
ValidateDomain(domain)
}
})
}
}
func BenchmarkValidateIP(b *testing.B) {
ips := []string{
"127.0.0.1",
"192.168.1.1",
"::1",
"2001:db8::1",
}
for _, ip := range ips {
b.Run(ip, func(b *testing.B) {
for i := 0; i < b.N; i++ {
ValidateIP(ip)
}
})
}
}
func BenchmarkIsBlockedDomain(b *testing.B) {
domains := []string{
"example.com", // not blocked
"apple.com", // blocked
"sub.icloud.com", // blocked subdomain
}
for _, domain := range domains {
b.Run(domain, func(b *testing.B) {
for i := 0; i < b.N; i++ {
IsBlockedDomain(domain)
}
})
}
}
func BenchmarkValidateConfig(b *testing.B) {
cfg := &Config{
Settings: Settings{AutoApply: true, FlushMethod: FlushMethodAuto},
Groups: []Group{
{
Name: "development",
Hosts: []Host{
{Domain: "a.example.com", IP: "127.0.0.1", Alias: "a", Enabled: true},
{Domain: "b.example.com", IP: "127.0.0.1", Alias: "b", Enabled: true},
{Domain: "c.example.com", IP: "127.0.0.1", Alias: "c", Enabled: false},
},
},
},
Presets: []Preset{
{Name: "local", Enable: []string{"a", "b"}, Disable: []string{"c"}},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := ValidateConfig(cfg)
require.NoError(b, err)
}
}