Files
Story Crater Bot b6767e247c
Build / Build and push image (push) Failing after 12s
CI / Test, vet, build (push) Successful in 2m18s
fix(deps,ci): update module path to forgejo.riotpiao.com/rock/homelab-frontend, switch to GITHUB_TOKEN
2026-08-21 20:46:45 -07:00

210 lines
7.9 KiB
Go

package config_test
import (
"testing"
"time"
"forgejo.riotpiao.com/rock/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)
}
}