LLM_BUSY_MODE=reject answers blocked LLM requests immediately with LLM_BUSY_STATUS (default 503, 429 works) and Retry-After, so routers like LiteLLM can cool down and retry instead of holding a hung connection. The default wait mode now also sends Retry-After when LLM_WAIT_TIMEOUT expires. Document the service account (LocalSystem default, NT SERVICE virtual-account hardening) and the Program Files / ProgramData install layout.
101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
package config
|
|
|
|
import (
|
|
"log/slog"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestDefaults(t *testing.T) {
|
|
cfg, err := Load(func(string) string { return "" })
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.ListenOllama != ":11434" || cfg.ListenComfy != ":8188" {
|
|
t.Fatalf("listen addrs = %s %s", cfg.ListenOllama, cfg.ListenComfy)
|
|
}
|
|
if cfg.UnloadTimeout != time.Minute || cfg.JobTimeout != 15*time.Minute {
|
|
t.Fatalf("timeouts = %v %v", cfg.UnloadTimeout, cfg.JobTimeout)
|
|
}
|
|
if !cfg.AutoUpdate || cfg.UpdateInterval != 6*time.Hour {
|
|
t.Fatalf("update = %v %v", cfg.AutoUpdate, cfg.UpdateInterval)
|
|
}
|
|
if cfg.LogLevel != slog.LevelWarn {
|
|
t.Fatalf("log level = %v", cfg.LogLevel)
|
|
}
|
|
}
|
|
|
|
func TestParseEnvFile(t *testing.T) {
|
|
input := `# comment
|
|
OLLAMA_URL=http://host:11435
|
|
|
|
LOGLEVEL=debug
|
|
SPACED = value with spaces
|
|
`
|
|
values, err := ParseEnvFile(strings.NewReader(input))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if values["OLLAMA_URL"] != "http://host:11435" {
|
|
t.Fatalf("OLLAMA_URL = %q", values["OLLAMA_URL"])
|
|
}
|
|
if values["LOGLEVEL"] != "debug" {
|
|
t.Fatalf("LOGLEVEL = %q", values["LOGLEVEL"])
|
|
}
|
|
if values["SPACED"] != "value with spaces" {
|
|
t.Fatalf("SPACED = %q", values["SPACED"])
|
|
}
|
|
}
|
|
|
|
func TestParseEnvFileMalformed(t *testing.T) {
|
|
_, err := ParseEnvFile(strings.NewReader("OK=1\nNOT_A_PAIR\n"))
|
|
if err == nil || !strings.Contains(err.Error(), "line 2") {
|
|
t.Fatalf("err = %v, want line 2 error", err)
|
|
}
|
|
}
|
|
|
|
func TestEnvOverridesFile(t *testing.T) {
|
|
file := map[string]string{"OLLAMA_URL": "http://file:1", "UNLOAD_TIMEOUT": "42s"}
|
|
env := map[string]string{"OLLAMA_URL": "http://env:2"}
|
|
getenv := func(k string) string {
|
|
if v := env[k]; v != "" {
|
|
return v
|
|
}
|
|
return file[k]
|
|
}
|
|
cfg, err := Load(getenv)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if cfg.OllamaURL != "http://env:2" {
|
|
t.Fatalf("OllamaURL = %q, want env value", cfg.OllamaURL)
|
|
}
|
|
if cfg.UnloadTimeout != 42*time.Second {
|
|
t.Fatalf("UnloadTimeout = %v, want file value", cfg.UnloadTimeout)
|
|
}
|
|
}
|
|
|
|
func TestLoadErrors(t *testing.T) {
|
|
for _, tc := range []struct{ key, value string }{
|
|
{"UNLOAD_TIMEOUT", "bogus"},
|
|
{"PROMPT_CAPTURE_LIMIT", "-5"},
|
|
{"AUTO_UPDATE", "maybe"},
|
|
{"LOGLEVEL", "shouty"},
|
|
{"LOG_FORMAT", "yaml"},
|
|
{"LLM_BUSY_MODE", "bogus"},
|
|
{"LLM_BUSY_STATUS", "200"},
|
|
{"BUSY_RETRY_AFTER", "0"},
|
|
} {
|
|
_, err := Load(func(k string) string {
|
|
if k == tc.key {
|
|
return tc.value
|
|
}
|
|
return ""
|
|
})
|
|
if err == nil {
|
|
t.Errorf("%s=%s: expected error", tc.key, tc.value)
|
|
}
|
|
}
|
|
}
|