ollama-proxy/internal/config/server_test.go
Atte149 3963eede70 feat: ollama-proxy — multi-account Ollama Cloud reverse proxy
Go reverse proxy for ollama.com that balances requests across multiple
API keys with round-robin and failover on 429/5xx. Exposes both native
Ollama API (/api/*) and OpenAI-compatible (/v1/*) passthrough.

- Round-robin balancer with per-account cooldown (60s default)
- Pre-stream failover: 429 → cooldown + next account; 5xx → next account
- Streaming invariant: once 2xx starts streaming, no account switch
- SSE (text/event-stream) and NDJSON passthrough with http.Flusher
- CLI: accounts add/list/remove/set-base-url, serve, version
- Accounts stored in ~/.config/ollama-proxy/accounts.json (chmod 0600)
- systemd unit (User=dueattendant149, 127.0.0.1:11435, Restart=always)
- 43 tests (unit + integration with httptest upstream)
- opencode integration: custom provider 'ocp' with explicit model list
- Requires NO_PROXY=127.0.0.1,localhost when HTTP_PROXY is set
2026-06-19 13:58:13 +03:00

103 lines
2.7 KiB
Go

package config
import (
"testing"
"time"
)
func TestDefaultServerConfig(t *testing.T) {
c := DefaultServerConfig()
if c.Addr != "127.0.0.1:11435" {
t.Errorf("Addr = %q", c.Addr)
}
if c.BaseURL != "https://ollama.com" {
t.Errorf("BaseURL = %q", c.BaseURL)
}
if c.Cooldown != 60*time.Second {
t.Errorf("Cooldown = %v", c.Cooldown)
}
if c.Retries != 3 {
t.Errorf("Retries = %d", c.Retries)
}
if c.LogLevel != "info" {
t.Errorf("LogLevel = %q", c.LogLevel)
}
}
func TestServerConfig_Validate(t *testing.T) {
good := DefaultServerConfig()
if err := good.Validate(); err != nil {
t.Errorf("default config invalid: %v", err)
}
cases := []struct {
name string
mut func(*ServerConfig)
}{
{"empty addr", func(c *ServerConfig) { c.Addr = "" }},
{"empty base_url", func(c *ServerConfig) { c.BaseURL = "" }},
{"bad scheme", func(c *ServerConfig) { c.BaseURL = "ftp://x" }},
{"negative cooldown", func(c *ServerConfig) { c.Cooldown = -1 * time.Second }},
{"zero retries", func(c *ServerConfig) { c.Retries = 0 }},
{"bad log level", func(c *ServerConfig) { c.LogLevel = "trace" }},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
c := DefaultServerConfig()
tc.mut(&c)
if err := c.Validate(); err == nil {
t.Errorf("Validate(%s) = nil, want error", tc.name)
}
})
}
}
func TestServerConfig_ApplyEnv(t *testing.T) {
t.Setenv("OLLAMA_PROXY_ADDR", "0.0.0.0:9000")
t.Setenv("OLLAMA_PROXY_BASE_URL", "https://staging.example.com")
t.Setenv("OLLAMA_PROXY_COOLDOWN", "120s")
t.Setenv("OLLAMA_PROXY_RETRIES", "5")
t.Setenv("OLLAMA_PROXY_LOG_LEVEL", "debug")
c := DefaultServerConfig()
c.ApplyEnv()
if c.Addr != "0.0.0.0:9000" {
t.Errorf("Addr = %q", c.Addr)
}
if c.BaseURL != "https://staging.example.com" {
t.Errorf("BaseURL = %q", c.BaseURL)
}
if c.Cooldown != 120*time.Second {
t.Errorf("Cooldown = %v", c.Cooldown)
}
if c.Retries != 5 {
t.Errorf("Retries = %d", c.Retries)
}
if c.LogLevel != "debug" {
t.Errorf("LogLevel = %q", c.LogLevel)
}
}
func TestServerConfig_ApplyEnv_IgnoresInvalid(t *testing.T) {
t.Setenv("OLLAMA_PROXY_COOLDOWN", "not-a-duration")
t.Setenv("OLLAMA_PROXY_RETRIES", "NaN")
t.Setenv("OLLAMA_PROXY_LOG_LEVEL", "trace")
t.Setenv("OLLAMA_PROXY_ADDR", "")
c := DefaultServerConfig()
c.ApplyEnv()
if c.Cooldown != 60*time.Second {
t.Errorf("bad cooldown env should be ignored, got %v", c.Cooldown)
}
if c.Retries != 3 {
t.Errorf("bad retries env should be ignored, got %d", c.Retries)
}
if c.LogLevel != "info" {
t.Errorf("bad log_level env should be ignored, got %q", c.LogLevel)
}
if c.Addr != "127.0.0.1:11435" {
t.Errorf("empty addr env should keep default, got %q", c.Addr)
}
}