373 lines
7.7 KiB
Go
373 lines
7.7 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
func TestLoad(t *testing.T) {
|
|
// Clean up any existing env vars
|
|
cleanup := cleanEnv()
|
|
defer cleanup()
|
|
|
|
// Set test values
|
|
os.Setenv("TECHNITIUM_URL", "https://test.dns.example.com")
|
|
os.Setenv("TECHNITIUM_TOKEN", "test-token-12345")
|
|
os.Setenv("BASE_DOMAIN", "test.rip")
|
|
os.Setenv("SPACE_SUBDOMAIN", "dyn")
|
|
os.Setenv("RATE_LIMIT_PER_IP", "20")
|
|
os.Setenv("RATE_LIMIT_PER_TOKEN", "5")
|
|
|
|
cfg := Load()
|
|
|
|
tests := []struct {
|
|
name string
|
|
got string
|
|
expected string
|
|
}{
|
|
{"TechnitiumURL", cfg.TechnitiumURL, "https://test.dns.example.com"},
|
|
{"TechnitiumToken", cfg.TechnitiumToken, "test-token-12345"},
|
|
{"BaseDomain", cfg.BaseDomain, "test.rip"},
|
|
{"SpaceSubdomain", cfg.SpaceSubdomain, "dyn"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.got != tt.expected {
|
|
t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test numeric values
|
|
if cfg.RateLimitPerIP != 20 {
|
|
t.Errorf("RateLimitPerIP = %v, want 20", cfg.RateLimitPerIP)
|
|
}
|
|
|
|
if cfg.RateLimitPerToken != 5 {
|
|
t.Errorf("RateLimitPerToken = %v, want 5", cfg.RateLimitPerToken)
|
|
}
|
|
}
|
|
|
|
func TestLoadDefaults(t *testing.T) {
|
|
cleanup := cleanEnv()
|
|
defer cleanup()
|
|
|
|
cfg := Load()
|
|
|
|
tests := []struct {
|
|
name string
|
|
got string
|
|
expected string
|
|
}{
|
|
{"ServerPort", cfg.ServerPort, "8080"},
|
|
{"DatabasePath", cfg.DatabasePath, "./dyn.db"},
|
|
{"BaseDomain", cfg.BaseDomain, "dws.rip"},
|
|
{"SpaceSubdomain", cfg.SpaceSubdomain, "space"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.got != tt.expected {
|
|
t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
|
|
// Test default numeric values
|
|
if cfg.RateLimitPerIP != 10 {
|
|
t.Errorf("RateLimitPerIP default = %v, want 10", cfg.RateLimitPerIP)
|
|
}
|
|
|
|
if cfg.RateLimitPerToken != 1 {
|
|
t.Errorf("RateLimitPerToken default = %v, want 1", cfg.RateLimitPerToken)
|
|
}
|
|
}
|
|
|
|
func TestValidate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
setupEnv func()
|
|
wantErrors int
|
|
}{
|
|
{
|
|
name: "valid config with token",
|
|
setupEnv: func() {
|
|
os.Setenv("TECHNITIUM_URL", "https://dns.example.com")
|
|
os.Setenv("TECHNITIUM_TOKEN", "valid-token")
|
|
},
|
|
wantErrors: 0,
|
|
},
|
|
{
|
|
name: "valid config with username/password",
|
|
setupEnv: func() {
|
|
os.Setenv("TECHNITIUM_URL", "https://dns.example.com")
|
|
os.Setenv("TECHNITIUM_USERNAME", "admin")
|
|
os.Setenv("TECHNITIUM_PASSWORD", "secret")
|
|
os.Unsetenv("TECHNITIUM_TOKEN")
|
|
},
|
|
wantErrors: 0,
|
|
},
|
|
{
|
|
name: "missing url",
|
|
setupEnv: func() {
|
|
os.Unsetenv("TECHNITIUM_URL")
|
|
os.Setenv("TECHNITIUM_TOKEN", "token")
|
|
},
|
|
wantErrors: 1,
|
|
},
|
|
{
|
|
name: "missing auth",
|
|
setupEnv: func() {
|
|
os.Setenv("TECHNITIUM_URL", "https://dns.example.com")
|
|
os.Unsetenv("TECHNITIUM_TOKEN")
|
|
os.Unsetenv("TECHNITIUM_USERNAME")
|
|
os.Unsetenv("TECHNITIUM_PASSWORD")
|
|
},
|
|
wantErrors: 1,
|
|
},
|
|
{
|
|
name: "missing everything",
|
|
setupEnv: func() {
|
|
os.Unsetenv("TECHNITIUM_URL")
|
|
os.Unsetenv("TECHNITIUM_TOKEN")
|
|
os.Unsetenv("TECHNITIUM_USERNAME")
|
|
os.Unsetenv("TECHNITIUM_PASSWORD")
|
|
},
|
|
wantErrors: 2,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cleanup := cleanEnv()
|
|
defer cleanup()
|
|
|
|
tt.setupEnv()
|
|
cfg := Load()
|
|
errors := cfg.Validate()
|
|
|
|
if len(errors) != tt.wantErrors {
|
|
t.Errorf("Validate() returned %d errors, want %d: %v", len(errors), tt.wantErrors, errors)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetZone(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
base string
|
|
space string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "with space subdomain",
|
|
base: "dws.rip",
|
|
space: "space",
|
|
expected: "space.dws.rip",
|
|
},
|
|
{
|
|
name: "without space subdomain",
|
|
base: "dws.rip",
|
|
space: "",
|
|
expected: "dws.rip",
|
|
},
|
|
{
|
|
name: "nested subdomain",
|
|
base: "example.com",
|
|
space: "dyn.space",
|
|
expected: "dyn.space.example.com",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
cfg := &Config{
|
|
BaseDomain: tt.base,
|
|
SpaceSubdomain: tt.space,
|
|
}
|
|
|
|
got := cfg.GetZone()
|
|
if got != tt.expected {
|
|
t.Errorf("GetZone() = %v, want %v", got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetEnv(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
key string
|
|
value string
|
|
defaultValue string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "env set",
|
|
key: "TEST_KEY",
|
|
value: "test-value",
|
|
defaultValue: "default",
|
|
expected: "test-value",
|
|
},
|
|
{
|
|
name: "env not set",
|
|
key: "UNSET_TEST_KEY",
|
|
value: "",
|
|
defaultValue: "default",
|
|
expected: "default",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if tt.value != "" {
|
|
os.Setenv(tt.key, tt.value)
|
|
defer os.Unsetenv(tt.key)
|
|
}
|
|
|
|
got := getEnv(tt.key, tt.defaultValue)
|
|
if got != tt.expected {
|
|
t.Errorf("getEnv() = %v, want %v", got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetEnvAsInt(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
value string
|
|
defaultValue int
|
|
expected int
|
|
}{
|
|
{
|
|
name: "valid int",
|
|
value: "42",
|
|
defaultValue: 10,
|
|
expected: 42,
|
|
},
|
|
{
|
|
name: "invalid int",
|
|
value: "not-a-number",
|
|
defaultValue: 10,
|
|
expected: 10,
|
|
},
|
|
{
|
|
name: "empty value",
|
|
value: "",
|
|
defaultValue: 10,
|
|
expected: 10,
|
|
},
|
|
{
|
|
name: "negative int",
|
|
value: "-5",
|
|
defaultValue: 10,
|
|
expected: -5,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
key := "TEST_INT_KEY"
|
|
if tt.value != "" {
|
|
os.Setenv(key, tt.value)
|
|
defer os.Unsetenv(key)
|
|
}
|
|
|
|
got := getEnvAsInt(key, tt.defaultValue)
|
|
if got != tt.expected {
|
|
t.Errorf("getEnvAsInt() = %v, want %v", got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetEnvAsSlice(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
value string
|
|
defaultValue []string
|
|
expected []string
|
|
}{
|
|
{
|
|
name: "single value",
|
|
value: "10.0.0.0/8",
|
|
defaultValue: []string{},
|
|
expected: []string{"10.0.0.0/8"},
|
|
},
|
|
{
|
|
name: "multiple values",
|
|
value: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16",
|
|
defaultValue: []string{},
|
|
expected: []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"},
|
|
},
|
|
{
|
|
name: "empty value",
|
|
value: "",
|
|
defaultValue: []string{"default"},
|
|
expected: []string{"default"},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
key := "TEST_SLICE_KEY"
|
|
if tt.value != "" {
|
|
os.Setenv(key, tt.value)
|
|
defer os.Unsetenv(key)
|
|
}
|
|
|
|
got := getEnvAsSlice(key, tt.defaultValue)
|
|
|
|
if len(got) != len(tt.expected) {
|
|
t.Errorf("getEnvAsSlice() length = %v, want %v", len(got), len(tt.expected))
|
|
return
|
|
}
|
|
|
|
for i, v := range got {
|
|
if v != tt.expected[i] {
|
|
t.Errorf("getEnvAsSlice()[%d] = %v, want %v", i, v, tt.expected[i])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// cleanEnv removes all DYN-related env vars and returns a cleanup function
|
|
func cleanEnv() func() {
|
|
vars := []string{
|
|
"SERVER_PORT",
|
|
"DATABASE_PATH",
|
|
"TECHNITIUM_URL",
|
|
"TECHNITIUM_USERNAME",
|
|
"TECHNITIUM_PASSWORD",
|
|
"TECHNITIUM_TOKEN",
|
|
"BASE_DOMAIN",
|
|
"SPACE_SUBDOMAIN",
|
|
"RATE_LIMIT_PER_IP",
|
|
"RATE_LIMIT_PER_TOKEN",
|
|
"TRUSTED_PROXIES",
|
|
}
|
|
|
|
// Store old values
|
|
oldValues := make(map[string]string)
|
|
for _, v := range vars {
|
|
if val, ok := os.LookupEnv(v); ok {
|
|
oldValues[v] = val
|
|
os.Unsetenv(v)
|
|
}
|
|
}
|
|
|
|
// Return cleanup function
|
|
return func() {
|
|
for _, v := range vars {
|
|
os.Unsetenv(v)
|
|
}
|
|
for v, val := range oldValues {
|
|
os.Setenv(v, val)
|
|
}
|
|
}
|
|
}
|