Files
homelab-frontend/internal/config/config_test.go
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

210 lines
7.9 KiB
Go

package config_test
import (
"testing"
"time"
"github.com/Riotpiaole/homelab-frontend/internal/config"
)
// TestLoadRoutesValidConfig tests that a valid configuration loads correctly.
func TestLoadRoutesValidConfig(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/valid.yaml")
if err != nil {
t.Fatalf("unexpected error loading valid config: %v", err)
}
// Verify all three routes are present
if len(routes) != 3 {
t.Errorf("expected 3 routes, got %d", len(routes))
}
// Verify reasoning-chat route
reasoningRoute, ok := routes["reasoning-chat"]
if !ok {
t.Fatal("reasoning-chat route not found")
}
if reasoningRoute.Name != "reasoning-chat" {
t.Errorf("route name mismatch: expected 'reasoning-chat', got %q", reasoningRoute.Name)
}
if reasoningRoute.Upstream.Address != "reasoning-predictor.llm-serving:80" {
t.Errorf("upstream address mismatch: expected 'reasoning-predictor.llm-serving:80', got %q", reasoningRoute.Upstream.Address)
}
if reasoningRoute.Upstream.ConnectTimeout != 10*time.Second {
t.Errorf("connect timeout mismatch: expected 10s, got %v", reasoningRoute.Upstream.ConnectTimeout)
}
if reasoningRoute.Upstream.ReadTimeout != time.Hour {
t.Errorf("read timeout mismatch: expected 1h, got %v", reasoningRoute.Upstream.ReadTimeout)
}
if reasoningRoute.Upstream.WriteTimeout != time.Hour {
t.Errorf("write timeout mismatch: expected 1h, got %v", reasoningRoute.Upstream.WriteTimeout)
}
if reasoningRoute.Upstream.MaxBodySize != 10485760 {
t.Errorf("max body size mismatch: expected 10485760, got %d", reasoningRoute.Upstream.MaxBodySize)
}
if !reasoningRoute.Upstream.AuthRequired {
t.Error("auth required should be true")
}
// Verify ornith-chat route
ornithRoute, ok := routes["ornith-chat"]
if !ok {
t.Fatal("ornith-chat route not found")
}
if ornithRoute.Upstream.ReadTimeout != 10*time.Minute {
t.Errorf("ornith read timeout mismatch: expected 10m, got %v", ornithRoute.Upstream.ReadTimeout)
}
if ornithRoute.Upstream.AuthRequired {
t.Error("ornith auth required should be false")
}
// Verify embeddings route
embeddingsRoute, ok := routes["embeddings"]
if !ok {
t.Fatal("embeddings route not found")
}
if embeddingsRoute.Upstream.MaxBodySize != 5242880 {
t.Errorf("embeddings max body size mismatch: expected 5242880, got %d", embeddingsRoute.Upstream.MaxBodySize)
}
}
// TestLoadRoutesMissingAddress tests that missing address field is caught.
func TestLoadRoutesMissingAddress(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/missing-address.yaml")
if err == nil {
t.Fatal("expected error for missing address, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": field 'address' is required" {
t.Errorf("expected error about missing address, got: %s", errMsg)
}
}
// TestLoadRoutesMissingConnectTimeout tests that missing connectTimeout field is caught.
func TestLoadRoutesMissingConnectTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/missing-connectTimeout.yaml")
if err == nil {
t.Fatal("expected error for missing connectTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": field 'connectTimeout' is required" {
t.Errorf("expected error about missing connectTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesMissingReadTimeout tests that missing readTimeout field is caught.
func TestLoadRoutesMissingReadTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/missing-readTimeout.yaml")
if err == nil {
t.Fatal("expected error for missing readTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": field 'readTimeout' is required" {
t.Errorf("expected error about missing readTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesMissingWriteTimeout tests that missing writeTimeout field is caught.
func TestLoadRoutesMissingWriteTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/missing-writeTimeout.yaml")
if err == nil {
t.Fatal("expected error for missing writeTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": field 'writeTimeout' is required" {
t.Errorf("expected error about missing writeTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesMissingMaxBodySize tests that missing maxBodySize field is caught.
func TestLoadRoutesMissingMaxBodySize(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/missing-maxBodySize.yaml")
if err == nil {
t.Fatal("expected error for missing maxBodySize, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": field 'maxBodySize' is required and must be > 0" {
t.Errorf("expected error about missing maxBodySize, got: %s", errMsg)
}
}
// TestLoadRoutesMalformedConnectTimeout tests that malformed connectTimeout is caught.
func TestLoadRoutesMalformedConnectTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/malformed-connectTimeout.yaml")
if err == nil {
t.Fatal("expected error for malformed connectTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": invalid connectTimeout \"not-a-duration\": time: invalid duration \"not-a-duration\"" {
t.Errorf("expected error about malformed connectTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesMalformedReadTimeout tests that malformed readTimeout is caught.
func TestLoadRoutesMalformedReadTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/malformed-readTimeout.yaml")
if err == nil {
t.Fatal("expected error for malformed readTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": invalid readTimeout \"invalid\": time: invalid duration \"invalid\"" {
t.Errorf("expected error about malformed readTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesMalformedWriteTimeout tests that malformed writeTimeout is caught.
func TestLoadRoutesMalformedWriteTimeout(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/malformed-writeTimeout.yaml")
if err == nil {
t.Fatal("expected error for malformed writeTimeout, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": invalid writeTimeout \"bad\": time: invalid duration \"bad\"" {
t.Errorf("expected error about malformed writeTimeout, got: %s", errMsg)
}
}
// TestLoadRoutesInvalidAddressNoPort tests that address without port is caught.
func TestLoadRoutesInvalidAddressNoPort(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/invalid-address-no-port.yaml")
if err == nil {
t.Fatal("expected error for invalid address (no port), got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "route \"test-route\": invalid address \"localhost\": address localhost: missing port in address" {
t.Errorf("expected error about invalid address, got: %s", errMsg)
}
}
// TestLoadRoutesDuplicateRouteNames tests that duplicate route names are caught.
func TestLoadRoutesDuplicateRouteNames(t *testing.T) {
routes, err := config.LoadRoutesFromFile("../../testdata/config/duplicate-routes.yaml")
if err == nil {
t.Fatal("expected error for duplicate routes, got nil")
}
if routes != nil {
t.Error("expected nil routes on error")
}
if errMsg := err.Error(); errMsg != "duplicate route: \"test-route\"" {
t.Errorf("expected error about duplicate routes, got: %s", errMsg)
}
}