package config import ( "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/zap" ) func TestConfig_Validate(t *testing.T) { tests := []struct { name string config *Config wantErr bool errMsg string }{ { name: "valid config", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "invalid port too low", config: &Config{ AppPort: 0, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "APP_PORT validation failed", }, { name: "invalid port too high", config: &Config{ AppPort: 99999, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "APP_PORT validation failed", }, { name: "JWT secret too short", config: &Config{ AppPort: 8080, JWTSecret: "short", DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "JWT_SECRET validation failed", }, { name: "JWT secret empty", config: &Config{ AppPort: 8080, JWTSecret: "", DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "JWT_SECRET validation failed", }, { name: "JWT secret exactly 32 characters", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "DatabaseURL empty", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "DATABASE_URL is required", }, { name: "RedisURL empty", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "REDIS_URL is required", }, { name: "DatabaseURL invalid format", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "invalid://database", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "DATABASE_URL validation failed", }, { name: "RedisURL invalid format", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "invalid://redis", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "REDIS_URL validation failed", }, { name: "DatabaseURL postgres format", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgres://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "DatabaseURL sqlite format", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "sqlite:///path/to/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "RedisURL rediss format (TLS)", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "rediss://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "valid port boundaries", config: &Config{ AppPort: 1, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "valid port upper boundary", config: &Config{ AppPort: 65535, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "invalid LogLevel", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", LogLevel: "INVALID", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "LOG_LEVEL validation failed", }, { name: "valid LogLevel", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", LogLevel: "DEBUG", RateLimitLimit: 100, // Added RateLimitWindow: 60, // Added }, wantErr: false, }, { name: "invalid RateLimitLimit zero", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 0, RateLimitWindow: 60, // Added }, wantErr: true, errMsg: "RATE_LIMIT_LIMIT validation failed", }, { name: "invalid RateLimitWindow negative", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, // Added RateLimitWindow: -1, }, wantErr: true, errMsg: "RATE_LIMIT_WINDOW validation failed", }, { name: "valid RateLimit values", config: &Config{ AppPort: 8080, JWTSecret: strings.Repeat("a", 32), DatabaseURL: "postgresql://user:pass@localhost:5432/db", RedisURL: "redis://localhost:6379", RateLimitLimit: 100, RateLimitWindow: 60, }, wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Ajouter un logger minimal si nécessaire pour éviter nil pointer if tt.config.Logger == nil { logger, _ := zap.NewDevelopment() tt.config.Logger = logger } err := tt.config.Validate() if tt.wantErr { require.Error(t, err) if tt.errMsg != "" { assert.Contains(t, err.Error(), tt.errMsg) } } else { require.NoError(t, err) } }) } }