go-agentic/config_test.go
Claude 23aa635c91
test: achieve 85.6% coverage with 7 new test files
Phase 1 complete: coverage from 70.1% to 85.6% (130+ tests, all passing).

New test files:
- lifecycle_test.go: full claim -> process -> complete integration flows
- allowance_edge_test.go: boundary conditions for token/job/concurrent limits
- allowance_error_test.go: mock errorStore covering all RecordUsage error paths
- embed_test.go: Prompt() hit/miss and content trimming
- service_test.go: DefaultServiceOptions, TaskPrompt, TaskCommit type coverage
- completion_git_test.go: real git repos for AutoCommit, CreateBranch, CommitAndSync
- context_git_test.go: findRelatedCode with keyword search, file limits, truncation

Updated config_test.go with YAML fallback, env override, and empty-dir paths.

Co-Authored-By: Charon <developers@lethean.io>
2026-02-20 00:59:58 +00:00

455 lines
13 KiB
Go

package agentic
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLoadConfig_Good_FromEnvFile(t *testing.T) {
// Create temp directory with .env file
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
envContent := `
AGENTIC_BASE_URL=https://test.api.com
AGENTIC_TOKEN=test-token-123
AGENTIC_PROJECT=my-project
AGENTIC_AGENT_ID=agent-001
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "https://test.api.com", cfg.BaseURL)
assert.Equal(t, "test-token-123", cfg.Token)
assert.Equal(t, "my-project", cfg.DefaultProject)
assert.Equal(t, "agent-001", cfg.AgentID)
}
func TestLoadConfig_Good_FromEnvVars(t *testing.T) {
// Create temp directory with .env file (partial config)
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
envContent := `
AGENTIC_TOKEN=env-file-token
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
// Set environment variables that should override
_ = os.Setenv("AGENTIC_BASE_URL", "https://env-override.com")
_ = os.Setenv("AGENTIC_TOKEN", "env-override-token")
defer func() {
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_TOKEN")
}()
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "https://env-override.com", cfg.BaseURL)
assert.Equal(t, "env-override-token", cfg.Token)
}
func TestLoadConfig_Bad_NoToken(t *testing.T) {
// Create temp directory without config
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
// Create empty .env
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(""), 0644)
require.NoError(t, err)
// Ensure no env vars are set
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_, err = LoadConfig(tmpDir)
assert.Error(t, err)
assert.Contains(t, err.Error(), "no authentication token")
}
func TestLoadConfig_Good_EnvFileWithQuotes(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
// Test with quoted values
envContent := `
AGENTIC_TOKEN="quoted-token"
AGENTIC_BASE_URL='single-quoted-url'
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "quoted-token", cfg.Token)
assert.Equal(t, "single-quoted-url", cfg.BaseURL)
}
func TestLoadConfig_Good_EnvFileWithComments(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
envContent := `
# This is a comment
AGENTIC_TOKEN=token-with-comments
# Another comment
AGENTIC_PROJECT=commented-project
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "token-with-comments", cfg.Token)
assert.Equal(t, "commented-project", cfg.DefaultProject)
}
func TestSaveConfig_Good(t *testing.T) {
// Create temp home directory
tmpHome, err := os.MkdirTemp("", "agentic-home")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpHome) }()
// Override HOME for the test
originalHome := os.Getenv("HOME")
_ = os.Setenv("HOME", tmpHome)
defer func() { _ = os.Setenv("HOME", originalHome) }()
cfg := &Config{
BaseURL: "https://saved.api.com",
Token: "saved-token",
DefaultProject: "saved-project",
AgentID: "saved-agent",
}
err = SaveConfig(cfg)
require.NoError(t, err)
// Verify file was created
configPath := filepath.Join(tmpHome, ".core", "agentic.yaml")
_, err = os.Stat(configPath)
assert.NoError(t, err)
// Read back the config
data, err := os.ReadFile(configPath)
require.NoError(t, err)
assert.Contains(t, string(data), "saved.api.com")
assert.Contains(t, string(data), "saved-token")
}
func TestConfigPath_Good(t *testing.T) {
path, err := ConfigPath()
require.NoError(t, err)
assert.Contains(t, path, ".core")
assert.Contains(t, path, "agentic.yaml")
}
func TestLoadConfig_Good_DefaultBaseURL(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
// Only provide token, should use default base URL
envContent := `
AGENTIC_TOKEN=test-token
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
// Clear any env overrides
_ = os.Unsetenv("AGENTIC_BASE_URL")
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, DefaultBaseURL, cfg.BaseURL)
}
func TestLoadConfig_Good_FromYAMLFallback(t *testing.T) {
// Set up a temp home with ~/.core/agentic.yaml
tmpHome, err := os.MkdirTemp("", "agentic-home")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpHome) }()
originalHome := os.Getenv("HOME")
_ = os.Setenv("HOME", tmpHome)
defer func() { _ = os.Setenv("HOME", originalHome) }()
// Clear all env vars so we fall through to YAML.
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
// Create ~/.core/agentic.yaml
configDir := filepath.Join(tmpHome, ".core")
err = os.MkdirAll(configDir, 0755)
require.NoError(t, err)
yamlContent := `base_url: https://yaml.api.com
token: yaml-token
default_project: yaml-project
agent_id: yaml-agent
`
err = os.WriteFile(filepath.Join(configDir, "agentic.yaml"), []byte(yamlContent), 0644)
require.NoError(t, err)
// Load from a dir with no .env to force YAML fallback.
tmpDir, err := os.MkdirTemp("", "agentic-noenv")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "https://yaml.api.com", cfg.BaseURL)
assert.Equal(t, "yaml-token", cfg.Token)
assert.Equal(t, "yaml-project", cfg.DefaultProject)
assert.Equal(t, "yaml-agent", cfg.AgentID)
}
func TestLoadConfig_Good_EnvOverridesYAML(t *testing.T) {
// Set up a temp home with ~/.core/agentic.yaml
tmpHome, err := os.MkdirTemp("", "agentic-home")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpHome) }()
originalHome := os.Getenv("HOME")
_ = os.Setenv("HOME", tmpHome)
defer func() { _ = os.Setenv("HOME", originalHome) }()
// Create ~/.core/agentic.yaml
configDir := filepath.Join(tmpHome, ".core")
err = os.MkdirAll(configDir, 0755)
require.NoError(t, err)
yamlContent := `base_url: https://yaml.api.com
token: yaml-token
`
err = os.WriteFile(filepath.Join(configDir, "agentic.yaml"), []byte(yamlContent), 0644)
require.NoError(t, err)
// Set env overrides for project and agent.
_ = os.Setenv("AGENTIC_PROJECT", "env-project")
_ = os.Setenv("AGENTIC_AGENT_ID", "env-agent")
defer func() {
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
}()
tmpDir, err := os.MkdirTemp("", "agentic-noenv")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "env-project", cfg.DefaultProject, "env var should override YAML")
assert.Equal(t, "env-agent", cfg.AgentID, "env var should override YAML")
}
func TestLoadConfig_Good_EnvFileWithTokenNoOverride(t *testing.T) {
// Test that .env with a token returns immediately without
// falling through to YAML.
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
envContent := `AGENTIC_TOKEN=env-file-only`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "env-file-only", cfg.Token)
assert.Equal(t, DefaultBaseURL, cfg.BaseURL)
}
func TestLoadConfig_Good_EnvFileWithMalformedLines(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
// Lines without = sign should be skipped.
envContent := `
AGENTIC_TOKEN=valid-token
MALFORMED_LINE_NO_EQUALS
ANOTHER_BAD_LINE
AGENTIC_PROJECT=valid-project
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "valid-token", cfg.Token)
assert.Equal(t, "valid-project", cfg.DefaultProject)
}
func TestApplyEnvOverrides_Good_AllVars(t *testing.T) {
_ = os.Setenv("AGENTIC_BASE_URL", "https://override-url.com")
_ = os.Setenv("AGENTIC_TOKEN", "override-token")
_ = os.Setenv("AGENTIC_PROJECT", "override-project")
_ = os.Setenv("AGENTIC_AGENT_ID", "override-agent")
defer func() {
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
}()
cfg := &Config{}
applyEnvOverrides(cfg)
assert.Equal(t, "https://override-url.com", cfg.BaseURL)
assert.Equal(t, "override-token", cfg.Token)
assert.Equal(t, "override-project", cfg.DefaultProject)
assert.Equal(t, "override-agent", cfg.AgentID)
}
func TestApplyEnvOverrides_Good_NoVarsSet(t *testing.T) {
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
cfg := &Config{
BaseURL: "original-url",
Token: "original-token",
}
applyEnvOverrides(cfg)
assert.Equal(t, "original-url", cfg.BaseURL, "should not change without env var")
assert.Equal(t, "original-token", cfg.Token, "should not change without env var")
}
func TestSaveConfig_Good_RoundTrip(t *testing.T) {
tmpHome, err := os.MkdirTemp("", "agentic-home")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpHome) }()
originalHome := os.Getenv("HOME")
_ = os.Setenv("HOME", tmpHome)
defer func() { _ = os.Setenv("HOME", originalHome) }()
// Clear env vars so LoadConfig falls through to YAML.
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
original := &Config{
BaseURL: "https://roundtrip.api.com",
Token: "roundtrip-token",
DefaultProject: "roundtrip-project",
AgentID: "roundtrip-agent",
}
err = SaveConfig(original)
require.NoError(t, err)
// Load it back by pointing to a dir with no .env.
tmpDir, err := os.MkdirTemp("", "agentic-noenv")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
loaded, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, original.BaseURL, loaded.BaseURL)
assert.Equal(t, original.Token, loaded.Token)
assert.Equal(t, original.DefaultProject, loaded.DefaultProject)
assert.Equal(t, original.AgentID, loaded.AgentID)
}
func TestLoadConfig_Good_EmptyDirUsesCurrentDir(t *testing.T) {
// Create a temp directory with .env and chdir into it.
tmpDir, err := os.MkdirTemp("", "agentic-cwd")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
envContent := `AGENTIC_TOKEN=cwd-token
AGENTIC_BASE_URL=https://cwd.api.com
`
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte(envContent), 0644)
require.NoError(t, err)
// Clear env vars.
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
// Save and restore cwd.
originalCwd, err := os.Getwd()
require.NoError(t, err)
defer func() { _ = os.Chdir(originalCwd) }()
err = os.Chdir(tmpDir)
require.NoError(t, err)
cfg, err := LoadConfig("")
require.NoError(t, err)
assert.Equal(t, "cwd-token", cfg.Token)
assert.Equal(t, "https://cwd.api.com", cfg.BaseURL)
}
func TestLoadConfig_Good_EnvFileNoToken_FallsToYAML(t *testing.T) {
tmpHome, err := os.MkdirTemp("", "agentic-home")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpHome) }()
originalHome := os.Getenv("HOME")
_ = os.Setenv("HOME", tmpHome)
defer func() { _ = os.Setenv("HOME", originalHome) }()
_ = os.Unsetenv("AGENTIC_TOKEN")
_ = os.Unsetenv("AGENTIC_BASE_URL")
_ = os.Unsetenv("AGENTIC_PROJECT")
_ = os.Unsetenv("AGENTIC_AGENT_ID")
// Create .env without a token.
tmpDir, err := os.MkdirTemp("", "agentic-test")
require.NoError(t, err)
defer func() { _ = os.RemoveAll(tmpDir) }()
err = os.WriteFile(filepath.Join(tmpDir, ".env"), []byte("AGENTIC_PROJECT=env-proj\n"), 0644)
require.NoError(t, err)
// Create YAML with token.
configDir := filepath.Join(tmpHome, ".core")
err = os.MkdirAll(configDir, 0755)
require.NoError(t, err)
yamlContent := `token: yaml-fallback-token
`
err = os.WriteFile(filepath.Join(configDir, "agentic.yaml"), []byte(yamlContent), 0644)
require.NoError(t, err)
cfg, err := LoadConfig(tmpDir)
require.NoError(t, err)
assert.Equal(t, "yaml-fallback-token", cfg.Token)
}