agent-orchestrator/backend/internal/config/config_test.go

138 lines
4.3 KiB
Go

package config
import (
"path/filepath"
"strings"
"testing"
"time"
)
func TestLoadDefaults(t *testing.T) {
// Clear every recognised var so we observe pure defaults regardless of the
// surrounding environment.
for _, k := range []string{"AO_PORT", "AO_REQUEST_TIMEOUT", "AO_SHUTDOWN_TIMEOUT", "AO_RUN_FILE", "AO_DATA_DIR"} {
t.Setenv(k, "")
}
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.Host != LoopbackHost {
t.Errorf("Host = %q, want %q", cfg.Host, LoopbackHost)
}
if cfg.Port != DefaultPort {
t.Errorf("Port = %d, want %d", cfg.Port, DefaultPort)
}
if cfg.RequestTimeout != DefaultRequestTimeout {
t.Errorf("RequestTimeout = %s, want %s", cfg.RequestTimeout, DefaultRequestTimeout)
}
if cfg.ShutdownTimeout != DefaultShutdownTimeout {
t.Errorf("ShutdownTimeout = %s, want %s", cfg.ShutdownTimeout, DefaultShutdownTimeout)
}
if cfg.RunFilePath == "" {
t.Error("RunFilePath is empty, want a resolved default path")
}
if !strings.HasSuffix(cfg.RunFilePath, filepath.Join(".ao", "running.json")) {
t.Errorf("RunFilePath = %q, want .ao/running.json suffix", cfg.RunFilePath)
}
if cfg.DataDir == "" {
t.Error("DataDir is empty, want a resolved default path")
}
if !strings.HasSuffix(cfg.DataDir, filepath.Join(".ao", "data")) {
t.Errorf("DataDir = %q, want .ao/data suffix", cfg.DataDir)
}
}
func TestLoadOverrides(t *testing.T) {
t.Setenv("AO_PORT", "4002")
t.Setenv("AO_REQUEST_TIMEOUT", "5s")
t.Setenv("AO_SHUTDOWN_TIMEOUT", "3s")
t.Setenv("AO_RUN_FILE", "/tmp/ao-test-running.json")
t.Setenv("AO_DATA_DIR", "/tmp/ao-test-data")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
if cfg.Addr() != "127.0.0.1:4002" {
t.Errorf("Addr() = %q, want 127.0.0.1:4002", cfg.Addr())
}
if cfg.RequestTimeout != 5*time.Second {
t.Errorf("RequestTimeout = %s, want 5s", cfg.RequestTimeout)
}
if cfg.ShutdownTimeout != 3*time.Second {
t.Errorf("ShutdownTimeout = %s, want 3s", cfg.ShutdownTimeout)
}
if cfg.RunFilePath != "/tmp/ao-test-running.json" {
t.Errorf("RunFilePath = %q, want /tmp/ao-test-running.json", cfg.RunFilePath)
}
if cfg.DataDir != "/tmp/ao-test-data" {
t.Errorf("DataDir = %q, want /tmp/ao-test-data", cfg.DataDir)
}
}
func TestLoadInvalid(t *testing.T) {
tests := []struct {
name string
env map[string]string
}{
{"non-numeric port", map[string]string{"AO_PORT": "abc"}},
{"port out of range", map[string]string{"AO_PORT": "70000"}},
{"bad request timeout", map[string]string{"AO_REQUEST_TIMEOUT": "soon"}},
{"bad shutdown timeout", map[string]string{"AO_SHUTDOWN_TIMEOUT": "later"}},
{"zero request timeout", map[string]string{"AO_REQUEST_TIMEOUT": "0s"}},
{"negative request timeout", map[string]string{"AO_REQUEST_TIMEOUT": "-1s"}},
{"zero shutdown timeout", map[string]string{"AO_SHUTDOWN_TIMEOUT": "0s"}},
{"negative shutdown timeout", map[string]string{"AO_SHUTDOWN_TIMEOUT": "-5s"}},
{"null origin", map[string]string{"AO_ALLOWED_ORIGINS": "app://renderer,null"}},
{"wildcard origin", map[string]string{"AO_ALLOWED_ORIGINS": "*"}},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
for k, v := range tc.env {
t.Setenv(k, v)
}
if _, err := Load(); err == nil {
t.Fatal("Load() = nil error, want error")
}
})
}
}
func TestLoadAllowedOrigins(t *testing.T) {
t.Run("default includes the packaged renderer origin", func(t *testing.T) {
t.Setenv("AO_ALLOWED_ORIGINS", "")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
found := false
for _, origin := range cfg.AllowedOrigins {
if origin == "app://renderer" {
found = true
}
}
if !found {
t.Errorf("AllowedOrigins = %v, want app://renderer included", cfg.AllowedOrigins)
}
})
t.Run("override replaces defaults and trims entries", func(t *testing.T) {
t.Setenv("AO_ALLOWED_ORIGINS", " app://renderer , http://localhost:9999 ,")
cfg, err := Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
want := []string{"app://renderer", "http://localhost:9999"}
if len(cfg.AllowedOrigins) != len(want) {
t.Fatalf("AllowedOrigins = %v, want %v", cfg.AllowedOrigins, want)
}
for i, origin := range want {
if cfg.AllowedOrigins[i] != origin {
t.Errorf("AllowedOrigins[%d] = %q, want %q", i, cfg.AllowedOrigins[i], origin)
}
}
})
}