vojo/apps/ai-bot/config_test.go

98 lines
3.1 KiB
Go

package main
import (
"strings"
"testing"
)
// setBaseEnv sets the minimal valid environment (all cascade flags off) so each test
// can toggle one combination and assert the fail-fast validation (F-FUNC-9).
func setBaseEnv(t *testing.T) {
t.Helper()
t.Setenv("HOMESERVER_URL", "http://hs")
t.Setenv("BOT_MXID", "@ai:vojo.chat")
t.Setenv("AS_TOKEN", "as")
t.Setenv("HS_TOKEN", "hs")
t.Setenv("XAI_API_KEY", "xai")
t.Setenv("AI_BOT_DATABASE_URL", "postgres://x")
t.Setenv("ALLOWED_SERVERS", "vojo.chat")
// Force a clean baseline so the host environment can't leak in.
for _, k := range []string{
"GEMINI_API_KEY", "GEMINI_API_KEY_FILE", "ROUTER_ENABLED", "ROUTER_CLASSIFIER_ENABLED",
"TRIVIAL_OFFLOAD_ENABLED", "WEB_ENABLED", "REASONING_ENABLED", "WEB_PROVIDER", "REASONING_MODEL",
} {
t.Setenv(k, "")
}
}
func TestConfigBaseValid(t *testing.T) {
setBaseEnv(t)
if _, err := LoadConfig(); err != nil {
t.Fatalf("base config should be valid: %v", err)
}
}
func TestConfigAllCascadeFlagsDefaultOff(t *testing.T) {
setBaseEnv(t)
cfg, err := LoadConfig()
if err != nil {
t.Fatalf("%v", err)
}
if cfg.RouterEnabled || cfg.RouterClassifierEnabled || cfg.TrivialOffloadEnabled ||
cfg.WebEnabled || cfg.ReasoningEnabled || cfg.TelemetryEnabled || cfg.GrokPromptCache {
t.Fatal("every cascade/telemetry flag must default off (cascade-off == today)")
}
if cfg.WebProvider != webProviderGrokWebSearch {
t.Fatalf("default WEB_PROVIDER = %q, want grok_web_search", cfg.WebProvider)
}
}
func TestConfigTrivialNeedsGeminiKey(t *testing.T) {
setBaseEnv(t)
t.Setenv("TRIVIAL_OFFLOAD_ENABLED", "true")
if _, err := LoadConfig(); err == nil || !strings.Contains(err.Error(), "GEMINI_API_KEY") {
t.Fatalf("want GEMINI_API_KEY error, got %v", err)
}
t.Setenv("GEMINI_API_KEY", "gk")
if _, err := LoadConfig(); err != nil {
t.Fatalf("with key it should be valid: %v", err)
}
}
func TestConfigClassifierNeedsRouter(t *testing.T) {
setBaseEnv(t)
t.Setenv("GEMINI_API_KEY", "gk")
t.Setenv("ROUTER_CLASSIFIER_ENABLED", "true") // without ROUTER_ENABLED
if _, err := LoadConfig(); err == nil || !strings.Contains(err.Error(), "ROUTER_ENABLED") {
t.Fatalf("want ROUTER_ENABLED error, got %v", err)
}
}
func TestConfigBadWebProvider(t *testing.T) {
setBaseEnv(t)
t.Setenv("WEB_ENABLED", "true")
t.Setenv("WEB_PROVIDER", "bing")
if _, err := LoadConfig(); err == nil || !strings.Contains(err.Error(), "WEB_PROVIDER") {
t.Fatalf("want WEB_PROVIDER error, got %v", err)
}
}
// The default web provider (grok_web_search) uses the existing xAI key, so WEB_ENABLED
// alone must NOT demand a Gemini key.
func TestConfigWebGrokNeedsNoGeminiKey(t *testing.T) {
setBaseEnv(t)
t.Setenv("WEB_ENABLED", "true")
if _, err := LoadConfig(); err != nil {
t.Fatalf("web+grok_web_search should not need a Gemini key: %v", err)
}
}
// gemini_grounding DOES need a Gemini key.
func TestConfigWebGeminiGroundingNeedsKey(t *testing.T) {
setBaseEnv(t)
t.Setenv("WEB_ENABLED", "true")
t.Setenv("WEB_PROVIDER", webProviderGeminiGrounding)
if _, err := LoadConfig(); err == nil || !strings.Contains(err.Error(), "GEMINI_API_KEY") {
t.Fatalf("want GEMINI_API_KEY error, got %v", err)
}
}