Files
token_thief/tests/config/config_test.go
T

306 lines
9.0 KiB
Go

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)
}
}