package config_test import ( "math" "net/netip" "strconv" "strings" "testing" "time" "git.misaka.ren/M1saka/token_thief/config" ) func TestLoadTimeoutDefaults(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.ReadTimeout != 30*time.Second { t.Fatalf("ReadTimeout=%s want 30s", cfg.ReadTimeout) } if cfg.WriteTimeout != 10*time.Minute { t.Fatalf("WriteTimeout=%s want 10m", cfg.WriteTimeout) } if cfg.IdleTimeout != 5*time.Minute { t.Fatalf("IdleTimeout=%s want 5m", cfg.IdleTimeout) } if cfg.UpstreamTimeout != 30*time.Second { t.Fatalf("UpstreamTimeout=%s want 30s", cfg.UpstreamTimeout) } if cfg.UpstreamResponseTimeout != 30*time.Second { t.Fatalf("UpstreamResponseTimeout=%s want 30s", cfg.UpstreamResponseTimeout) } if cfg.UpstreamStreamIdleTimeout != 2*time.Minute { t.Fatalf("UpstreamStreamIdleTimeout=%s want 2m", cfg.UpstreamStreamIdleTimeout) } } func TestLoadQueueDefaults(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.MaxBodyBytes != 1<<20 { t.Fatalf("MaxBodyBytes=%d want %d", cfg.MaxBodyBytes, 1<<20) } if cfg.MaxRequestBytes != 16<<20 { t.Fatalf("MaxRequestBytes=%d want %d", cfg.MaxRequestBytes, 16<<20) } if cfg.LogQueueSize != 256 { t.Fatalf("LogQueueSize=%d want 256", cfg.LogQueueSize) } if cfg.LogQueueBytes != 64<<20 { t.Fatalf("LogQueueBytes=%d want %d", cfg.LogQueueBytes, 64<<20) } } func TestLoadTimeoutOverrides(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv("READ_TIMEOUT", "10s") t.Setenv("WRITE_TIMEOUT", "20s") t.Setenv("IDLE_TIMEOUT", "30s") t.Setenv("UPSTREAM_TIMEOUT", "40s") t.Setenv("UPSTREAM_RESPONSE_TIMEOUT", "50s") t.Setenv("UPSTREAM_STREAM_IDLE_TIMEOUT", "60s") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.ReadTimeout != 10*time.Second { t.Fatalf("ReadTimeout=%s want 10s", cfg.ReadTimeout) } if cfg.WriteTimeout != 20*time.Second { t.Fatalf("WriteTimeout=%s want 20s", cfg.WriteTimeout) } if cfg.IdleTimeout != 30*time.Second { t.Fatalf("IdleTimeout=%s want 30s", cfg.IdleTimeout) } if cfg.UpstreamTimeout != 40*time.Second { t.Fatalf("UpstreamTimeout=%s want 40s", cfg.UpstreamTimeout) } if cfg.UpstreamResponseTimeout != 50*time.Second { t.Fatalf("UpstreamResponseTimeout=%s want 50s", cfg.UpstreamResponseTimeout) } if cfg.UpstreamStreamIdleTimeout != 60*time.Second { t.Fatalf("UpstreamStreamIdleTimeout=%s want 60s", cfg.UpstreamStreamIdleTimeout) } } func TestLoadRejectsInvalidTypedValues(t *testing.T) { tests := []struct { name string key string value string }{ {name: "int", key: "LOG_QUEUE_SIZE", value: "not-an-int"}, {name: "int64", key: "MAX_BODY_BYTES", value: "1.5"}, {name: "duration", key: "READ_TIMEOUT", value: "30"}, {name: "bool", key: "UPSTREAM_TLS_INSECURE_SKIP_VERIFY", value: "yes"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv(tt.key, tt.value) _, err := config.Load() if err == nil { t.Fatalf("Load succeeded with %s=%q", tt.key, tt.value) } if !strings.Contains(err.Error(), tt.key) { t.Fatalf("err=%q does not identify %s", err, tt.key) } }) } } func TestLoadRejectsNonPositiveNumericAndDurationValues(t *testing.T) { tests := []struct { key string value string }{ {key: "MAX_BODY_BYTES", value: "0"}, {key: "LOG_QUEUE_SIZE", value: "-1"}, {key: "LOG_QUEUE_BYTES", value: "0"}, {key: "LOG_BATCH_SIZE", value: "0"}, {key: "LOG_BATCH_INTERVAL", value: "-1s"}, {key: "LOG_WORKERS", value: "0"}, {key: "DB_RECONNECT_INTERVAL", value: "0s"}, {key: "READ_TIMEOUT", value: "0s"}, {key: "WRITE_TIMEOUT", value: "0s"}, {key: "IDLE_TIMEOUT", value: "0s"}, {key: "UPSTREAM_TIMEOUT", value: "0s"}, {key: "UPSTREAM_RESPONSE_TIMEOUT", value: "0s"}, {key: "UPSTREAM_STREAM_IDLE_TIMEOUT", value: "0s"}, } for _, tt := range tests { t.Run(tt.key, func(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv(tt.key, tt.value) _, err := config.Load() if err == nil { t.Fatalf("Load succeeded with %s=%q", tt.key, tt.value) } if !strings.Contains(err.Error(), tt.key) { t.Fatalf("err=%q does not identify %s", err, tt.key) } }) } } func TestLoadTrustedProxies(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv("TRUSTED_PROXIES", "10.0.0.0/8, 192.0.2.1,2001:db8::/32, 2001:db8::1") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } want := []netip.Prefix{ netip.MustParsePrefix("10.0.0.0/8"), netip.MustParsePrefix("192.0.2.1/32"), netip.MustParsePrefix("2001:db8::/32"), netip.MustParsePrefix("2001:db8::1/128"), } if len(cfg.TrustedProxies) != len(want) { t.Fatalf("TrustedProxies=%v want %v", cfg.TrustedProxies, want) } for i := range want { if cfg.TrustedProxies[i] != want[i] { t.Fatalf("TrustedProxies[%d]=%v want %v", i, cfg.TrustedProxies[i], want[i]) } } } func TestLoadRejectsInvalidTrustedProxies(t *testing.T) { for _, value := range []string{"not-an-ip", "10.0.0.0/33", "10.0.0.1/8", "10.0.0.1,,192.0.2.1"} { t.Run(value, func(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv("TRUSTED_PROXIES", value) _, err := config.Load() if err == nil { t.Fatalf("Load succeeded with TRUSTED_PROXIES=%q", value) } }) } } func TestLoadUpstreamTLSInsecureSkipVerifyDefault(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.UpstreamTLSInsecureSkipVerify { t.Fatal("UpstreamTLSInsecureSkipVerify=true want false") } } func TestLoadUpstreamTLSInsecureSkipVerifyOverride(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv("UPSTREAM_TLS_INSECURE_SKIP_VERIFY", "true") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if !cfg.UpstreamTLSInsecureSkipVerify { t.Fatal("UpstreamTLSInsecureSkipVerify=false want true") } } func TestLoadRequiresClickHouseURL(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("DATABASE_URL", "postgres://user:pass@localhost/db") _, err := config.Load() if err == nil { t.Fatal("Load succeeded without CLICKHOUSE_URL") } if err.Error() != "CLICKHOUSE_URL is required" { t.Fatalf("err=%q want CLICKHOUSE_URL is required", err.Error()) } } func TestLoadRejectsUnsupportedUpstreamScheme(t *testing.T) { t.Setenv("UPSTREAM_URL", "ftp://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") if _, err := config.Load(); err == nil { t.Fatal("Load succeeded with unsupported UPSTREAM_URL scheme") } } func TestLoadRejectsMaxRequestBytesOverflowBoundary(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouse://user:pass@localhost:9000/db") t.Setenv("MAX_REQUEST_BYTES", strconv.FormatInt(math.MaxInt64, 10)) if _, err := config.Load(); err == nil || !strings.Contains(err.Error(), "MAX_REQUEST_BYTES") { t.Fatalf("Load error=%v, want MAX_REQUEST_BYTES rejection", err) } } func TestLoadValidatesClickHouseURL(t *testing.T) { tests := []struct { name string dsn string }{ {name: "missing port", dsn: "clickhouse://user:pass@localhost/db"}, {name: "unsupported scheme", dsn: "https://localhost:9440/db"}, {name: "plaintext skip verify", dsn: "clickhouse://localhost:9000/db?skip_verify=true"}, {name: "conflicting secure parameter", dsn: "clickhouses://localhost:9440/db?secure=false"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", tt.dsn) _, err := config.Load() if err == nil { t.Fatalf("Load succeeded with CLICKHOUSE_URL=%q", tt.dsn) } if !strings.Contains(err.Error(), "CLICKHOUSE_URL") { t.Fatalf("err=%q does not identify CLICKHOUSE_URL", err) } }) } } func TestLoadAcceptsSecureClickHouseURL(t *testing.T) { t.Setenv("UPSTREAM_URL", "https://example.com") t.Setenv("CLICKHOUSE_URL", "clickhouses://user:pass@localhost:9440/db?skip_verify=false") cfg, err := config.Load() if err != nil { t.Fatalf("Load: %v", err) } if cfg.ClickHouseURL != "clickhouses://user:pass@localhost:9440/db?skip_verify=false" { t.Fatalf("ClickHouseURL=%q", cfg.ClickHouseURL) } }