niko_trust/internal/server/config_test.go
Niko Marmeladkov d957108ac1
feat: YAML config for all server tunables
- server.Config + DefaultConfig + LoadConfig/ParseConfig (yaml.v3)
- all operator knobs now configurable: listen addr, audience, data dir,
  log level, per-IP rate limits, per-subject quota, challenge/session TTLs,
  max body bytes
- server.New takes Config; flags (-addr/-audience/-data/-config) override the
  file; missing config.yaml falls back to defaults
- config.yaml.example committed as template; config.yaml git-ignored
- tests for config defaults/parsing/partial override
2026-08-25 21:11:49 +03:00

72 lines
2 KiB
Go

package server
import (
"testing"
"time"
)
func TestDefaultConfig(t *testing.T) {
c := DefaultConfig()
if c.ListenAddr != ":8080" || c.Audience != "trust.n1ko.dev" {
t.Fatalf("unexpected defaults: %+v", c)
}
if c.PutLimit != 60 || c.PutWindow != time.Minute {
t.Fatalf("unexpected rate-limit defaults: %+v", c)
}
if c.MaxPerSubject != 1000 || c.ChallengeTTL != 5*time.Minute || c.SessionTTL != 30*time.Minute {
t.Fatalf("unexpected auth defaults: %+v", c)
}
}
func TestParseConfig(t *testing.T) {
yaml := []byte(`
listen_addr: ":9090"
audience: "relay.example"
data_dir: "/var/lib/trust"
log_level: "debug"
put_limit: 10
put_window: "2m"
challenge_limit: 5
challenge_window: "30s"
max_per_subject: 50
challenge_ttl: "1m"
session_ttl: "10m"
max_body_bytes: 2048
`)
c, err := ParseConfig(yaml)
if err != nil {
t.Fatal(err)
}
if c.ListenAddr != ":9090" || c.Audience != "relay.example" || c.DataDir != "/var/lib/trust" || c.LogLevel != "debug" {
t.Fatalf("scalars not overridden: %+v", c)
}
if c.PutLimit != 10 || c.PutWindow != 2*time.Minute {
t.Fatalf("put limit not parsed: %+v", c)
}
if c.ChallengeLimit != 5 || c.ChallengeWindow != 30*time.Second {
t.Fatalf("challenge limit not parsed: %+v", c)
}
if c.MaxPerSubject != 50 || c.ChallengeTTL != time.Minute || c.SessionTTL != 10*time.Minute {
t.Fatalf("auth knobs not parsed: %+v", c)
}
if c.MaxBodyBytes != 2048 {
t.Fatalf("max_body_bytes not parsed: %+v", c)
}
}
func TestParseConfigPartial(t *testing.T) {
// Unset keys fall back to defaults; badly-formatted durations are ignored.
c, err := ParseConfig([]byte("put_limit: 7\nput_window: \"not-a-duration\"\n"))
if err != nil {
t.Fatal(err)
}
if c.PutLimit != 7 {
t.Fatalf("put_limit should be 7, got %d", c.PutLimit)
}
if c.PutWindow != time.Minute {
t.Fatalf("invalid duration should fall back to default, got %v", c.PutWindow)
}
if c.MaxPerSubject != 1000 {
t.Fatalf("unset max_per_subject should keep default, got %d", c.MaxPerSubject)
}
}