summaryrefslogtreecommitdiffstats
path: root/internal/config/config_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/config/config_test.go')
-rw-r--r--internal/config/config_test.go288
1 files changed, 288 insertions, 0 deletions
diff --git a/internal/config/config_test.go b/internal/config/config_test.go
new file mode 100644
index 0000000..50d9b67
--- /dev/null
+++ b/internal/config/config_test.go
@@ -0,0 +1,288 @@
1package config
2
3import (
4 "os"
5 "testing"
6 "time"
7)
8
9func TestDefault(t *testing.T) {
10 cfg := Default()
11
12 if cfg.Server.GrpcAddr != ":50051" {
13 t.Errorf("expected default grpc_addr :50051, got %s", cfg.Server.GrpcAddr)
14 }
15
16 if cfg.Database.Path != "relay.db" {
17 t.Errorf("expected default db path relay.db, got %s", cfg.Database.Path)
18 }
19
20 if cfg.Metrics.Enabled != true {
21 t.Error("expected metrics enabled by default")
22 }
23}
24
25func TestLoadYAML(t *testing.T) {
26 // Create temporary config file
27 tmpfile, err := os.CreateTemp("", "config-*.yaml")
28 if err != nil {
29 t.Fatal(err)
30 }
31 defer os.Remove(tmpfile.Name())
32
33 configData := `
34server:
35 grpc_addr: ":9999"
36 http_addr: ":8888"
37
38database:
39 path: "test.db"
40
41auth:
42 enabled: true
43 required: true
44 timestamp_window: 120
45
46rate_limit:
47 enabled: true
48 default_rps: 50
49 default_burst: 100
50
51metrics:
52 enabled: true
53 addr: ":9191"
54 namespace: "test"
55`
56
57 if _, err := tmpfile.Write([]byte(configData)); err != nil {
58 t.Fatal(err)
59 }
60 tmpfile.Close()
61
62 // Load config
63 cfg, err := Load(tmpfile.Name())
64 if err != nil {
65 t.Fatalf("failed to load config: %v", err)
66 }
67
68 // Verify values
69 if cfg.Server.GrpcAddr != ":9999" {
70 t.Errorf("expected grpc_addr :9999, got %s", cfg.Server.GrpcAddr)
71 }
72
73 if cfg.Database.Path != "test.db" {
74 t.Errorf("expected db path test.db, got %s", cfg.Database.Path)
75 }
76
77 if !cfg.Auth.Enabled {
78 t.Error("expected auth enabled")
79 }
80
81 if !cfg.Auth.Required {
82 t.Error("expected auth required")
83 }
84
85 if cfg.Auth.TimestampWindow != 120 {
86 t.Errorf("expected timestamp window 120, got %d", cfg.Auth.TimestampWindow)
87 }
88
89 if cfg.RateLimit.DefaultRPS != 50 {
90 t.Errorf("expected rate limit 50, got %.1f", cfg.RateLimit.DefaultRPS)
91 }
92
93 if cfg.Metrics.Namespace != "test" {
94 t.Errorf("expected metrics namespace test, got %s", cfg.Metrics.Namespace)
95 }
96}
97
98func TestEnvOverrides(t *testing.T) {
99 // Set environment variables
100 os.Setenv("MUXSTR_SERVER_GRPC_ADDR", ":7777")
101 os.Setenv("MUXSTR_AUTH_ENABLED", "true")
102 os.Setenv("MUXSTR_RATE_LIMIT_DEFAULT_RPS", "200")
103 defer func() {
104 os.Unsetenv("MUXSTR_SERVER_GRPC_ADDR")
105 os.Unsetenv("MUXSTR_AUTH_ENABLED")
106 os.Unsetenv("MUXSTR_RATE_LIMIT_DEFAULT_RPS")
107 }()
108
109 // Load with empty file (just defaults + env)
110 cfg, err := Load("")
111 if err != nil {
112 t.Fatalf("failed to load config: %v", err)
113 }
114
115 // Verify env overrides
116 if cfg.Server.GrpcAddr != ":7777" {
117 t.Errorf("expected env override :7777, got %s", cfg.Server.GrpcAddr)
118 }
119
120 if !cfg.Auth.Enabled {
121 t.Error("expected auth enabled from env")
122 }
123
124 if cfg.RateLimit.DefaultRPS != 200 {
125 t.Errorf("expected rate limit 200 from env, got %.1f", cfg.RateLimit.DefaultRPS)
126 }
127}
128
129func TestValidation(t *testing.T) {
130 tests := []struct {
131 name string
132 cfg *Config
133 wantErr bool
134 }{
135 {
136 name: "valid default config",
137 cfg: Default(),
138 wantErr: false,
139 },
140 {
141 name: "missing grpc_addr",
142 cfg: &Config{
143 Server: ServerConfig{
144 HttpAddr: ":8080",
145 },
146 Database: DatabaseConfig{
147 Path: "test.db",
148 },
149 },
150 wantErr: true,
151 },
152 {
153 name: "missing http_addr",
154 cfg: &Config{
155 Server: ServerConfig{
156 GrpcAddr: ":50051",
157 },
158 Database: DatabaseConfig{
159 Path: "test.db",
160 },
161 },
162 wantErr: true,
163 },
164 {
165 name: "missing database path",
166 cfg: &Config{
167 Server: ServerConfig{
168 GrpcAddr: ":50051",
169 HttpAddr: ":8080",
170 },
171 Database: DatabaseConfig{},
172 },
173 wantErr: true,
174 },
175 {
176 name: "invalid log level",
177 cfg: &Config{
178 Server: ServerConfig{
179 GrpcAddr: ":50051",
180 HttpAddr: ":8080",
181 },
182 Database: DatabaseConfig{
183 Path: "test.db",
184 },
185 Logging: LoggingConfig{
186 Level: "invalid",
187 Format: "json",
188 },
189 },
190 wantErr: true,
191 },
192 }
193
194 for _, tt := range tests {
195 t.Run(tt.name, func(t *testing.T) {
196 err := tt.cfg.Validate()
197 if (err != nil) != tt.wantErr {
198 t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
199 }
200 })
201 }
202}
203
204func TestSaveAndLoad(t *testing.T) {
205 // Create config
206 cfg := Default()
207 cfg.Server.GrpcAddr = ":9999"
208 cfg.Auth.Enabled = true
209 cfg.RateLimit.DefaultRPS = 100
210
211 // Save to temp file
212 tmpfile, err := os.CreateTemp("", "config-*.yaml")
213 if err != nil {
214 t.Fatal(err)
215 }
216 defer os.Remove(tmpfile.Name())
217 tmpfile.Close()
218
219 if err := cfg.Save(tmpfile.Name()); err != nil {
220 t.Fatalf("failed to save config: %v", err)
221 }
222
223 // Load it back
224 loaded, err := Load(tmpfile.Name())
225 if err != nil {
226 t.Fatalf("failed to load config: %v", err)
227 }
228
229 // Verify
230 if loaded.Server.GrpcAddr != ":9999" {
231 t.Errorf("expected grpc_addr :9999, got %s", loaded.Server.GrpcAddr)
232 }
233
234 if !loaded.Auth.Enabled {
235 t.Error("expected auth enabled")
236 }
237
238 if loaded.RateLimit.DefaultRPS != 100 {
239 t.Errorf("expected rate limit 100, got %.1f", loaded.RateLimit.DefaultRPS)
240 }
241}
242
243func TestDurationParsing(t *testing.T) {
244 // Create config with durations
245 tmpfile, err := os.CreateTemp("", "config-*.yaml")
246 if err != nil {
247 t.Fatal(err)
248 }
249 defer os.Remove(tmpfile.Name())
250
251 configData := `
252server:
253 grpc_addr: ":50051"
254 http_addr: ":8080"
255 read_timeout: "1m"
256 write_timeout: "2m"
257
258database:
259 path: "test.db"
260 max_lifetime: "30m"
261
262rate_limit:
263 cleanup_interval: "10m"
264 max_idle_time: "20m"
265`
266
267 if _, err := tmpfile.Write([]byte(configData)); err != nil {
268 t.Fatal(err)
269 }
270 tmpfile.Close()
271
272 cfg, err := Load(tmpfile.Name())
273 if err != nil {
274 t.Fatalf("failed to load config: %v", err)
275 }
276
277 if cfg.Server.ReadTimeout != 1*time.Minute {
278 t.Errorf("expected read timeout 1m, got %v", cfg.Server.ReadTimeout)
279 }
280
281 if cfg.Server.WriteTimeout != 2*time.Minute {
282 t.Errorf("expected write timeout 2m, got %v", cfg.Server.WriteTimeout)
283 }
284
285 if cfg.Database.MaxLifetime != 30*time.Minute {
286 t.Errorf("expected max lifetime 30m, got %v", cfg.Database.MaxLifetime)
287 }
288}