Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ibe9c357ea2c56a967c75be04c2099f536a6a6964
213 lines
5 KiB
Go
213 lines
5 KiB
Go
package config_test
|
|
|
|
import (
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"notashelf.dev/ncro/internal/config"
|
|
)
|
|
|
|
func TestLoadDefaults(t *testing.T) {
|
|
cfg, err := config.Load("")
|
|
if err != nil {
|
|
t.Fatalf("Load(\"\") error: %v", err)
|
|
}
|
|
if cfg.Server.Listen != ":8080" {
|
|
t.Errorf("default listen = %q, want :8080", cfg.Server.Listen)
|
|
}
|
|
if len(cfg.Upstreams) == 0 {
|
|
t.Error("expected at least one default upstream")
|
|
}
|
|
if cfg.Cache.MaxEntries != 100000 {
|
|
t.Errorf("default max_entries = %d, want 100000", cfg.Cache.MaxEntries)
|
|
}
|
|
}
|
|
|
|
func TestLoadFromYAML(t *testing.T) {
|
|
yamlContent := `
|
|
server:
|
|
listen: ":9090"
|
|
upstreams:
|
|
- url: "https://cache.nixos.org"
|
|
priority: 10
|
|
cache:
|
|
db_path: "/tmp/test.db"
|
|
max_entries: 500
|
|
`
|
|
f, _ := os.CreateTemp("", "ncro-*.yaml")
|
|
defer os.Remove(f.Name())
|
|
f.WriteString(yamlContent)
|
|
f.Close()
|
|
|
|
cfg, err := config.Load(f.Name())
|
|
if err != nil {
|
|
t.Fatalf("Load error: %v", err)
|
|
}
|
|
if cfg.Server.Listen != ":9090" {
|
|
t.Errorf("listen = %q, want :9090", cfg.Server.Listen)
|
|
}
|
|
if cfg.Cache.MaxEntries != 500 {
|
|
t.Errorf("max_entries = %d, want 500", cfg.Cache.MaxEntries)
|
|
}
|
|
}
|
|
|
|
func TestEnvOverride(t *testing.T) {
|
|
t.Setenv("NCRO_LISTEN", ":1234")
|
|
cfg, err := config.Load("")
|
|
if err != nil {
|
|
t.Fatalf("Load error: %v", err)
|
|
}
|
|
if cfg.Server.Listen != ":1234" {
|
|
t.Errorf("env override listen = %q, want :1234", cfg.Server.Listen)
|
|
}
|
|
}
|
|
|
|
func TestDurationParsing(t *testing.T) {
|
|
yamlContent := `
|
|
server:
|
|
listen: ":8080"
|
|
read_timeout: 30s
|
|
write_timeout: 1m
|
|
cache:
|
|
ttl: 2h
|
|
mesh:
|
|
gossip_interval: 45s
|
|
`
|
|
f, _ := os.CreateTemp("", "ncro-dur-*.yaml")
|
|
defer os.Remove(f.Name())
|
|
f.WriteString(yamlContent)
|
|
f.Close()
|
|
|
|
cfg, err := config.Load(f.Name())
|
|
if err != nil {
|
|
t.Fatalf("Load error: %v", err)
|
|
}
|
|
if cfg.Server.ReadTimeout.Duration != 30*time.Second {
|
|
t.Errorf("read_timeout = %v, want 30s", cfg.Server.ReadTimeout.Duration)
|
|
}
|
|
if cfg.Server.WriteTimeout.Duration != time.Minute {
|
|
t.Errorf("write_timeout = %v, want 1m", cfg.Server.WriteTimeout.Duration)
|
|
}
|
|
if cfg.Cache.TTL.Duration != 2*time.Hour {
|
|
t.Errorf("ttl = %v, want 2h", cfg.Cache.TTL.Duration)
|
|
}
|
|
if cfg.Mesh.GossipInterval.Duration != 45*time.Second {
|
|
t.Errorf("gossip_interval = %v, want 45s", cfg.Mesh.GossipInterval.Duration)
|
|
}
|
|
}
|
|
|
|
func TestValidateValid(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
if err := cfg.Validate(); err != nil {
|
|
t.Errorf("default config should be valid: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestValidateNoUpstreams(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Upstreams = nil
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for no upstreams")
|
|
}
|
|
}
|
|
|
|
func TestValidateBadURL(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Upstreams = []config.UpstreamConfig{{URL: "not-a-url"}}
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for invalid URL")
|
|
}
|
|
}
|
|
|
|
func TestValidateBadAlpha(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Cache.LatencyAlpha = 0
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for alpha=0")
|
|
}
|
|
cfg.Cache.LatencyAlpha = 1
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for alpha=1")
|
|
}
|
|
}
|
|
|
|
func TestValidateZeroTTL(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Cache.TTL = config.Duration{}
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for zero TTL")
|
|
}
|
|
}
|
|
|
|
func TestValidateNegativeTTL(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Cache.NegativeTTL = config.Duration{}
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for zero negative_ttl")
|
|
}
|
|
}
|
|
|
|
func TestValidateMeshEnabledNoPeers(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Mesh.Enabled = true
|
|
cfg.Mesh.Peers = nil
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for mesh enabled without peers")
|
|
}
|
|
}
|
|
|
|
func TestValidateMeshBadPeerKey(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Mesh.Enabled = true
|
|
cfg.Mesh.Peers = []config.PeerConfig{
|
|
{Addr: "127.0.0.1:7946", PublicKey: "not-hex!"},
|
|
}
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for invalid mesh peer public key")
|
|
}
|
|
}
|
|
|
|
func TestValidateUpstreamBadPublicKey(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Upstreams = []config.UpstreamConfig{
|
|
{URL: "https://cache.nixos.org", PublicKey: "no-colon-here"},
|
|
}
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for upstream public_key missing ':'")
|
|
}
|
|
}
|
|
|
|
func TestCachePriorityDefault(t *testing.T) {
|
|
cfg, err := config.Load("")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.Server.CachePriority != 30 {
|
|
t.Errorf("default CachePriority = %d, want 30", cfg.Server.CachePriority)
|
|
}
|
|
}
|
|
|
|
func TestCachePriorityValidation(t *testing.T) {
|
|
cfg, _ := config.Load("")
|
|
cfg.Server.CachePriority = 0
|
|
if err := cfg.Validate(); err == nil {
|
|
t.Error("expected error for CachePriority = 0")
|
|
}
|
|
}
|
|
|
|
func TestInvalidDuration(t *testing.T) {
|
|
yamlContent := `
|
|
server:
|
|
read_timeout: "bananas"
|
|
`
|
|
f, _ := os.CreateTemp("", "ncro-bad-*.yaml")
|
|
defer os.Remove(f.Name())
|
|
f.WriteString(yamlContent)
|
|
f.Close()
|
|
|
|
_, err := config.Load(f.Name())
|
|
if err == nil {
|
|
t.Error("expected error for invalid duration string, got nil")
|
|
}
|
|
}
|