veza/veza-backend-api/internal/config/validator_test.go
2025-12-03 20:29:37 +01:00

232 lines
5.7 KiB
Go

package config
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestConfigValidator_ValidatePort(t *testing.T) {
validator := NewConfigValidator()
tests := []struct {
name string
port int
wantErr bool
}{
{"valid port", 8080, false},
{"min port", 1, false},
{"max port", 65535, false},
{"invalid negative", -1, true},
{"invalid too high", 65536, true},
{"invalid zero", 0, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validator.ValidatePort(tt.port)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestConfigValidator_ValidateURL(t *testing.T) {
validator := NewConfigValidator()
tests := []struct {
name string
url string
expectedScheme string
wantErr bool
}{
{"valid postgres URL", "postgres://user:pass@localhost:5432/db", "postgres", false},
{"valid postgresql URL", "postgresql://user:pass@localhost:5432/db", "postgresql", false},
{"valid redis URL", "redis://localhost:6379", "redis", false},
{"valid rediss URL", "rediss://localhost:6380", "rediss", false},
{"invalid scheme", "http://localhost", "postgres", true},
{"empty URL", "", "postgres", true},
{"malformed URL", "://invalid", "postgres", true},
{"missing scheme", "localhost:5432/db", "postgres", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validator.ValidateURL(tt.url, tt.expectedScheme)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestConfigValidator_ValidateEnum(t *testing.T) {
validator := NewConfigValidator()
tests := []struct {
name string
value string
allowed []string
wantErr bool
}{
{
name: "valid value in enum",
value: "INFO",
allowed: []string{"DEBUG", "INFO", "WARN", "ERROR"},
wantErr: false,
},
{
name: "case sensitive match",
value: "info",
allowed: []string{"INFO", "WARN"},
wantErr: true,
},
{
name: "value not in enum",
value: "TRACE",
allowed: []string{"DEBUG", "INFO", "WARN", "ERROR"},
wantErr: true,
},
{
name: "empty value with empty allowed",
value: "",
allowed: []string{},
wantErr: true,
},
{
name: "empty value in allowed",
value: "",
allowed: []string{"", "value1"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validator.ValidateEnum(tt.value, tt.allowed)
if tt.wantErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), "not allowed")
} else {
assert.NoError(t, err)
}
})
}
}
func TestConfigValidator_ValidateSecretLength(t *testing.T) {
validator := NewConfigValidator()
tests := []struct {
name string
secret string
minLength int
wantErr bool
}{
{"valid secret", "my-super-secret-key-that-is-long-enough", 32, false},
{"exact length", strings.Repeat("a", 32), 32, false},
{"too short", "short", 32, true},
{"empty secret", "", 1, true},
{"empty secret with min 0", "", 0, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validator.ValidateSecretLength(tt.secret, tt.minLength)
if tt.wantErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), "at least")
} else {
assert.NoError(t, err)
}
})
}
}
func TestConfigValidator_ValidatePositiveInt(t *testing.T) {
validator := NewConfigValidator()
tests := []struct {
name string
value int
fieldName string
wantErr bool
}{
{"valid positive", 42, "test_field", false},
{"valid one", 1, "test_field", false},
{"invalid zero", 0, "test_field", true},
{"invalid negative", -1, "test_field", true},
{"invalid large negative", -1000, "test_field", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validator.ValidatePositiveInt(tt.value, tt.fieldName)
if tt.wantErr {
assert.Error(t, err)
assert.Contains(t, err.Error(), "must be positive")
assert.Contains(t, err.Error(), tt.fieldName)
} else {
assert.NoError(t, err)
}
})
}
}
func TestNewConfigValidator(t *testing.T) {
validator := NewConfigValidator()
assert.NotNil(t, validator)
}
func TestConfigValidator_ValidateURL_MultipleSchemes(t *testing.T) {
validator := NewConfigValidator()
// Test avec différents schémas PostgreSQL
err1 := validator.ValidateURL("postgres://localhost/db", "postgres")
assert.NoError(t, err1)
err2 := validator.ValidateURL("postgresql://localhost/db", "postgresql")
assert.NoError(t, err2)
// Test avec schéma Redis
err3 := validator.ValidateURL("redis://localhost:6379", "redis")
assert.NoError(t, err3)
err4 := validator.ValidateURL("rediss://localhost:6380", "rediss")
assert.NoError(t, err4)
}
func TestConfigValidator_ValidateEnum_ErrorMessages(t *testing.T) {
validator := NewConfigValidator()
err := validator.ValidateEnum("invalid", []string{"valid1", "valid2", "valid3"})
require.Error(t, err)
assert.Contains(t, err.Error(), "not allowed")
assert.Contains(t, err.Error(), "valid1, valid2, valid3")
}
func TestConfigValidator_ValidateSecretLength_ErrorMessages(t *testing.T) {
validator := NewConfigValidator()
err := validator.ValidateSecretLength("short", 32)
require.Error(t, err)
assert.Contains(t, err.Error(), "at least 32")
assert.Contains(t, err.Error(), "got 5")
}
func TestConfigValidator_ValidatePositiveInt_ErrorMessages(t *testing.T) {
validator := NewConfigValidator()
err := validator.ValidatePositiveInt(-5, "rate_limit")
require.Error(t, err)
assert.Contains(t, err.Error(), "rate_limit")
assert.Contains(t, err.Error(), "must be positive")
assert.Contains(t, err.Error(), "got -5")
}