Files
galaxy-game/gamemaster/internal/config/config_test.go
T
2026-05-03 07:59:03 +02:00

170 lines
5.9 KiB
Go

package config
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func validEnv(t *testing.T) {
t.Helper()
t.Setenv("GAMEMASTER_INTERNAL_HTTP_ADDR", ":8097")
t.Setenv("GAMEMASTER_POSTGRES_PRIMARY_DSN", "postgres://gm:secret@localhost:5432/galaxy?search_path=gamemaster&sslmode=disable")
t.Setenv("GAMEMASTER_REDIS_MASTER_ADDR", "localhost:6379")
t.Setenv("GAMEMASTER_REDIS_PASSWORD", "secret")
t.Setenv("GAMEMASTER_LOBBY_INTERNAL_BASE_URL", "http://lobby:8095")
t.Setenv("GAMEMASTER_RTM_INTERNAL_BASE_URL", "http://rtmanager:8096")
}
func TestLoadFromEnvAcceptsDefaults(t *testing.T) {
validEnv(t)
cfg, err := LoadFromEnv()
require.NoError(t, err)
require.Equal(t, ":8097", cfg.InternalHTTP.Addr)
require.Equal(t, 30*time.Second, cfg.ShutdownTimeout)
require.Equal(t, "info", cfg.Logging.Level)
require.Equal(t, "gm:lobby_events", cfg.Streams.LobbyEvents)
require.Equal(t, "runtime:health_events", cfg.Streams.HealthEvents)
require.Equal(t, "notification:intents", cfg.Streams.NotificationIntents)
require.Equal(t, 5*time.Second, cfg.Streams.BlockTimeout)
require.Equal(t, 30*time.Second, cfg.EngineClient.CallTimeout)
require.Equal(t, 5*time.Second, cfg.EngineClient.ProbeTimeout)
require.Equal(t, "http://lobby:8095", cfg.Lobby.BaseURL)
require.Equal(t, 2*time.Second, cfg.Lobby.Timeout)
require.Equal(t, "http://rtmanager:8096", cfg.RTM.BaseURL)
require.Equal(t, 5*time.Second, cfg.RTM.Timeout)
require.Equal(t, time.Second, cfg.Scheduler.TickInterval)
require.Equal(t, 60*time.Second, cfg.Scheduler.TurnGenerationTimeout)
require.Equal(t, 30*time.Second, cfg.MembershipCache.TTL)
require.Equal(t, 4096, cfg.MembershipCache.MaxGames)
require.Equal(t, "galaxy-gamemaster", cfg.Telemetry.ServiceName)
}
func TestLoadFromEnvHonoursOverrides(t *testing.T) {
validEnv(t)
t.Setenv("GAMEMASTER_INTERNAL_HTTP_ADDR", ":9097")
t.Setenv("GAMEMASTER_REDIS_LOBBY_EVENTS_STREAM", "custom:lobby_events")
t.Setenv("GAMEMASTER_ENGINE_CALL_TIMEOUT", "45s")
t.Setenv("GAMEMASTER_SCHEDULER_TICK_INTERVAL", "500ms")
t.Setenv("GAMEMASTER_MEMBERSHIP_CACHE_TTL", "60s")
t.Setenv("GAMEMASTER_MEMBERSHIP_CACHE_MAX_GAMES", "1024")
cfg, err := LoadFromEnv()
require.NoError(t, err)
require.Equal(t, ":9097", cfg.InternalHTTP.Addr)
require.Equal(t, "custom:lobby_events", cfg.Streams.LobbyEvents)
require.Equal(t, 45*time.Second, cfg.EngineClient.CallTimeout)
require.Equal(t, 500*time.Millisecond, cfg.Scheduler.TickInterval)
require.Equal(t, 60*time.Second, cfg.MembershipCache.TTL)
require.Equal(t, 1024, cfg.MembershipCache.MaxGames)
}
func TestLoadFromEnvRequiresInternalHTTPAddr(t *testing.T) {
t.Setenv("GAMEMASTER_POSTGRES_PRIMARY_DSN", "postgres://gm:secret@localhost:5432/galaxy")
t.Setenv("GAMEMASTER_REDIS_MASTER_ADDR", "localhost:6379")
t.Setenv("GAMEMASTER_REDIS_PASSWORD", "secret")
t.Setenv("GAMEMASTER_LOBBY_INTERNAL_BASE_URL", "http://lobby:8095")
t.Setenv("GAMEMASTER_RTM_INTERNAL_BASE_URL", "http://rtmanager:8096")
_, err := LoadFromEnv()
require.Error(t, err)
require.Contains(t, err.Error(), "GAMEMASTER_INTERNAL_HTTP_ADDR")
}
func TestLoadFromEnvRequiresLobbyBaseURL(t *testing.T) {
t.Setenv("GAMEMASTER_INTERNAL_HTTP_ADDR", ":8097")
t.Setenv("GAMEMASTER_POSTGRES_PRIMARY_DSN", "postgres://gm:secret@localhost:5432/galaxy")
t.Setenv("GAMEMASTER_REDIS_MASTER_ADDR", "localhost:6379")
t.Setenv("GAMEMASTER_REDIS_PASSWORD", "secret")
t.Setenv("GAMEMASTER_RTM_INTERNAL_BASE_URL", "http://rtmanager:8096")
_, err := LoadFromEnv()
require.Error(t, err)
require.Contains(t, err.Error(), "GAMEMASTER_LOBBY_INTERNAL_BASE_URL")
}
func TestLoadFromEnvRequiresRTMBaseURL(t *testing.T) {
t.Setenv("GAMEMASTER_INTERNAL_HTTP_ADDR", ":8097")
t.Setenv("GAMEMASTER_POSTGRES_PRIMARY_DSN", "postgres://gm:secret@localhost:5432/galaxy")
t.Setenv("GAMEMASTER_REDIS_MASTER_ADDR", "localhost:6379")
t.Setenv("GAMEMASTER_REDIS_PASSWORD", "secret")
t.Setenv("GAMEMASTER_LOBBY_INTERNAL_BASE_URL", "http://lobby:8095")
_, err := LoadFromEnv()
require.Error(t, err)
require.Contains(t, err.Error(), "GAMEMASTER_RTM_INTERNAL_BASE_URL")
}
func TestLoadFromEnvRejectsBadLogLevel(t *testing.T) {
validEnv(t)
t.Setenv("GAMEMASTER_LOG_LEVEL", "verbose")
_, err := LoadFromEnv()
require.Error(t, err)
require.Contains(t, err.Error(), "GAMEMASTER_LOG_LEVEL")
}
func TestLoadFromEnvRejectsBadDuration(t *testing.T) {
validEnv(t)
t.Setenv("GAMEMASTER_ENGINE_CALL_TIMEOUT", "thirty seconds")
_, err := LoadFromEnv()
require.Error(t, err)
require.Contains(t, err.Error(), "GAMEMASTER_ENGINE_CALL_TIMEOUT")
}
func TestInternalHTTPValidateRejectsBadAddr(t *testing.T) {
cfg := DefaultConfig().InternalHTTP
cfg.Addr = "not-an-addr"
err := cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "host:port")
}
func TestStreamsValidateRequiresAllNames(t *testing.T) {
cfg := DefaultConfig().Streams
cfg.LobbyEvents = " "
err := cfg.Validate()
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), "lobby events"))
}
func TestLobbyClientValidateRejectsBadURL(t *testing.T) {
cfg := LobbyClientConfig{BaseURL: "ftp://lobby", Timeout: time.Second}
err := cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "http(s)")
}
func TestRTMClientValidateRejectsEmptyURL(t *testing.T) {
cfg := RTMClientConfig{BaseURL: " ", Timeout: time.Second}
err := cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "rtm internal base url")
}
func TestSchedulerValidateRejectsZeroInterval(t *testing.T) {
cfg := SchedulerConfig{TickInterval: 0, TurnGenerationTimeout: time.Second}
err := cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "scheduler tick interval")
}
func TestMembershipCacheValidateRejectsZero(t *testing.T) {
cfg := MembershipCacheConfig{TTL: 0, MaxGames: 1}
err := cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "ttl")
cfg = MembershipCacheConfig{TTL: time.Second, MaxGames: 0}
err = cfg.Validate()
require.Error(t, err)
require.Contains(t, err.Error(), "max games")
}