internal/config/config_test.go (view raw)
1package config
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7)
8
9func TestDefaultConfig(t *testing.T) {
10 cfg := DefaultConfig()
11
12 if cfg.MaxArticlesPerFeed != 10 {
13 t.Errorf("Expected MaxArticlesPerFeed = 10, got %d", cfg.MaxArticlesPerFeed)
14 }
15
16 if cfg.MaxDaysOld != 7 {
17 t.Errorf("Expected MaxDaysOld = 7, got %d", cfg.MaxDaysOld)
18 }
19
20 if cfg.MaxTotalArticles != 20 {
21 t.Errorf("Expected MaxTotalArticles = 20, got %d", cfg.MaxTotalArticles)
22 }
23
24 if cfg.Model != "deepseek-chat" {
25 t.Errorf("Expected Model = 'deepseek-chat', got %s", cfg.Model)
26 }
27
28 if cfg.MaxTokens != 4000 {
29 t.Errorf("Expected MaxTokens = 4000, got %d", cfg.MaxTokens)
30 }
31
32 if cfg.Temperature != 0.7 {
33 t.Errorf("Expected Temperature = 0.7, got %f", cfg.Temperature)
34 }
35
36 expectedPrompt := `You are an expert analyst and summariser.
37You analyse content from multiple sources and provide
38concise, insightful summaries based on user requests.
39Focus on key points, trends, and important information.`
40
41 if cfg.SystemPrompt != expectedPrompt {
42 t.Errorf("SystemPrompt doesn't match expected default")
43 }
44
45 if cfg.Output != "text" {
46 t.Errorf("Expected Output = 'text', got %s", cfg.Output)
47 }
48}
49
50func TestConfigPath(t *testing.T) {
51 path, err := GetConfigPath()
52 if err != nil {
53 t.Fatalf("Failed to get config path: %v", err)
54 }
55
56 // Should end with .config/llm_aggregator/config.toml
57 expectedSuffix := filepath.Join(".config", "llm_aggregator", "config.toml")
58 if !hasSuffix(path, expectedSuffix) {
59 t.Errorf("Config path %s doesn't end with %s", path, expectedSuffix)
60 }
61}
62
63func TestConfigSaveAndLoad(t *testing.T) {
64 // Create temporary directory for test
65 tempDir := t.TempDir()
66 oldEnv := os.Getenv("XDG_CONFIG_HOME")
67 os.Setenv("XDG_CONFIG_HOME", tempDir)
68 defer os.Setenv("XDG_CONFIG_HOME", oldEnv)
69
70 cfg := DefaultConfig()
71 cfg.SystemPrompt = "Test system prompt"
72 cfg.Model = "test-model"
73 cfg.MaxTokens = 1234
74
75 // Save config
76 if err := cfg.Save(); err != nil {
77 t.Fatalf("Failed to save config: %v", err)
78 }
79
80 // Verify file exists
81 configPath, err := GetConfigPath()
82 if err != nil {
83 t.Fatalf("Failed to get config path: %v", err)
84 }
85
86 if _, err := os.Stat(configPath); os.IsNotExist(err) {
87 t.Fatalf("Config file not created at %s", configPath)
88 }
89
90 // Load config
91 loadedCfg, err := Load()
92 if err != nil {
93 t.Fatalf("Failed to load config: %v", err)
94 }
95
96 if !loadedCfg.IsLoaded() {
97 t.Error("Config should be marked as loaded")
98 }
99
100 if loadedCfg.SystemPrompt != cfg.SystemPrompt {
101 t.Errorf("SystemPrompt mismatch: expected %q, got %q", cfg.SystemPrompt, loadedCfg.SystemPrompt)
102 }
103
104 if loadedCfg.Model != cfg.Model {
105 t.Errorf("Model mismatch: expected %s, got %s", cfg.Model, loadedCfg.Model)
106 }
107
108 if loadedCfg.MaxTokens != cfg.MaxTokens {
109 t.Errorf("MaxTokens mismatch: expected %d, got %d", cfg.MaxTokens, loadedCfg.MaxTokens)
110 }
111}
112
113func TestEnvironmentVariables(t *testing.T) {
114 // Create temporary directory for test
115 tempDir := t.TempDir()
116 oldEnv := os.Getenv("XDG_CONFIG_HOME")
117 os.Setenv("XDG_CONFIG_HOME", tempDir)
118 defer os.Setenv("XDG_CONFIG_HOME", oldEnv)
119
120 // Set environment variables
121 os.Setenv("LLM_AGGREGATOR_SYSTEM_PROMPT", "Env system prompt")
122 os.Setenv("LLM_AGGREGATOR_MODEL", "env-model")
123 os.Setenv("LLM_AGGREGATOR_MAX_TOKENS", "9999")
124 defer func() {
125 os.Unsetenv("LLM_AGGREGATOR_SYSTEM_PROMPT")
126 os.Unsetenv("LLM_AGGREGATOR_MODEL")
127 os.Unsetenv("LLM_AGGREGATOR_MAX_TOKENS")
128 }()
129
130 // Load config (should pick up env vars)
131 cfg, err := Load()
132 if err != nil {
133 t.Fatalf("Failed to load config: %v", err)
134 }
135
136 if cfg.SystemPrompt != "Env system prompt" {
137 t.Errorf("SystemPrompt should be from env var, got %q", cfg.SystemPrompt)
138 }
139
140 if cfg.Model != "env-model" {
141 t.Errorf("Model should be from env var, got %s", cfg.Model)
142 }
143
144 if cfg.MaxTokens != 9999 {
145 t.Errorf("MaxTokens should be from env var, got %d", cfg.MaxTokens)
146 }
147}
148
149func TestConfigExists(t *testing.T) {
150 // Create temporary directory for test
151 tempDir := t.TempDir()
152 oldEnv := os.Getenv("XDG_CONFIG_HOME")
153 os.Setenv("XDG_CONFIG_HOME", tempDir)
154 defer os.Setenv("XDG_CONFIG_HOME", oldEnv)
155
156 // Get config path to verify
157 configPath, err := GetConfigPath()
158 if err != nil {
159 t.Fatalf("Failed to get config path: %v", err)
160 }
161
162 // Ensure it's in our temp directory
163 if !contains(configPath, tempDir) {
164 t.Logf("Config path %s not in temp dir %s", configPath, tempDir)
165 }
166
167 // Initially should not exist
168 exists, err := ConfigExists()
169 if err != nil {
170 t.Fatalf("Failed to check config existence: %v", err)
171 }
172
173 if exists {
174 // Config exists, maybe from previous test run
175 t.Logf("Config exists at %s, removing...", configPath)
176 os.Remove(configPath)
177 // Check again
178 exists, err = ConfigExists()
179 if err != nil {
180 t.Fatalf("Failed to check config existence after removal: %v", err)
181 }
182 if exists {
183 t.Error("Config should not exist after removal")
184 }
185 }
186
187 // Create config
188 cfg := DefaultConfig()
189 if err := cfg.Save(); err != nil {
190 t.Fatalf("Failed to save config: %v", err)
191 }
192
193 // Now should exist
194 exists, err = ConfigExists()
195 if err != nil {
196 t.Fatalf("Failed to check config existence: %v", err)
197 }
198
199 if !exists {
200 t.Error("Config should exist after saving")
201 }
202}
203
204// Helper function to check if path has suffix
205func hasSuffix(path, suffix string) bool {
206 if len(path) < len(suffix) {
207 return false
208 }
209 return path[len(path)-len(suffix):] == suffix
210}
211
212// Helper function to check if string contains substring
213func contains(s, substr string) bool {
214 return len(s) >= len(substr) && (s == substr || len(substr) == 0 ||
215 (s[0:len(substr)] == substr || contains(s[1:], substr)))
216}