package config import ( "path/filepath" "strings" "testing" ) // 本文件钉住「重置为 env 默认」动作(切片 R1)的**对照基准读取**:`.env` 默认层必须 // 按既有解析入口读(同一份 parseDotEnv + 同一份 `env:"…"` 标签解码器),优先级与 // Load 逐字一致(进程环境 > `.env` > 标签默认),且读不出时明确报错——绝不回一份 // 空快照冒充「env 什么都没声明」。 // // 它刻意只解 LLM 子树:整份 Load 会在缺 JWT_SECRET 这类必填项时失败,而本读取不需要 // 它们(第一个用例就把这条钉住)。 func TestLoadLLMDefaultsReadsEnvFileWithoutRequiredConfig(t *testing.T) { // 这份 `.env` 故意不含 JWT_SECRET 等必填项:本读取只解 LLM 子树,不该因此失败。 path := writeEnvFile(t, strings.Join([]string{ "# 注释与空行照旧被忽略", "LLM_BASE_URL=https://env.example/v1", "LLM_API_KEY=sk-env-plaintext", "LLM_MODEL=env-model", "LLM_CONTEXT_WINDOW=131072", "ANTHROPIC_MODEL=env-claude", "", }, "\n")) llm, err := LoadLLMDefaults(path) if err != nil { t.Fatalf("LoadLLMDefaults: %v", err) } if llm.Provider != "openai" || llm.BaseURL != "https://env.example/v1" || llm.APIKey != "sk-env-plaintext" || llm.Model != "env-model" || llm.ContextWindow != 131072 { t.Fatalf("llm = %+v, want `.env` 里逐字声明的扁平块(LLM_PROVIDER 未声明 ⇒ 标签默认 openai)", llm) } if llm.AnthropicModel != "env-claude" { t.Fatalf("AnthropicModel = %q, want env-claude(同一份解码器覆盖全部 LLM_*/ANTHROPIC_* 标签)", llm.AnthropicModel) } } func TestLoadLLMDefaultsProcessEnvWinsOverEnvFile(t *testing.T) { path := writeEnvFile(t, "LLM_MODEL=from-file\n") t.Setenv("LLM_MODEL", "from-process") // 该键没被声明:必须仍是零值(空),不能被 `.env` 的其它行牵连。 t.Setenv("LLM_BASE_URL", "") llm, err := LoadLLMDefaults(path) if err != nil { t.Fatalf("LoadLLMDefaults: %v", err) } if llm.Model != "from-process" { t.Fatalf("Model = %q, want from-process(优先级必须与 Load 一致:进程环境 > .env)", llm.Model) } } func TestLoadLLMDefaultsUnreadableSourceFails(t *testing.T) { // 目录不是可读的 `.env`:读取必须明确报错,而不是静默回一份空声明。 dir := t.TempDir() if _, err := LoadLLMDefaults(dir); err == nil { t.Fatal("对目录调用 LoadLLMDefaults 应报错, want 明确错误") } // 不存在的文件按 `.env` 的开发期约定容忍(parseDotEnv 的既有语义):结果是 // 「只按进程环境与标签默认」的一份快照,而不是错误。 missing := filepath.Join(t.TempDir(), "absent.env") llm, err := LoadLLMDefaults(missing) if err != nil { t.Fatalf("文件缺失应容忍(.env 只是开发期便利): %v", err) } if llm.Provider != "openai" || llm.BaseURL != "" { t.Fatalf("llm = %+v, want 标签默认 + 空串(没有 `.env` 可读)", llm) } } func TestLoadLLMDefaultsRejectsNegativeContextWindow(t *testing.T) { path := writeEnvFile(t, "LLM_CONTEXT_WINDOW=-1\n") if _, err := LoadLLMDefaults(path); err == nil { t.Fatal("负数窗口应报错(与 Load 同一口径:窗口没有负数语义)") } }