Files
bot-pontos/backend/internal/config/config_test.go
2026-10-23 22:31:02 -03:00

112 lines
3.1 KiB
Go

package config
import (
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func env(values map[string]string) func(string) string {
return func(key string) string { return values[key] }
}
func TestLoadDefaults(t *testing.T) {
cfg, err := load(env(map[string]string{
"BP_DB_USER": "botpontos_app",
"BP_DB_PASSWORD": "segredo",
}))
if err != nil {
t.Fatalf("erro inesperado: %v", err)
}
if cfg.DB.Host != "postgres" || cfg.DB.Port != 5432 || cfg.DB.Name != "botpontos" {
t.Errorf("padrões do banco inesperados: %+v", cfg.DB)
}
if cfg.HTTP.Addr != ":8080" || cfg.Worker.HealthAddr != ":8081" {
t.Errorf("endereços inesperados: api=%s worker=%s", cfg.HTTP.Addr, cfg.Worker.HealthAddr)
}
if cfg.Jobs.ReconciliationInterval != 15*time.Minute {
t.Errorf("reconciliação = %s, esperado 15m", cfg.Jobs.ReconciliationInterval)
}
if cfg.Jobs.DispatchInterval != 2*time.Minute {
t.Errorf("despacho = %s, esperado 2m", cfg.Jobs.DispatchInterval)
}
if cfg.Jobs.LateTolerance != 10*time.Minute {
t.Errorf("tolerância = %s, esperado 10m", cfg.Jobs.LateTolerance)
}
if cfg.Jobs.APIFailureThreshold != 3 {
t.Errorf("limite de falhas = %d, esperado 3", cfg.Jobs.APIFailureThreshold)
}
}
func TestLoadSecretFromFile(t *testing.T) {
path := filepath.Join(t.TempDir(), "pg_app_password")
if err := os.WriteFile(path, []byte("segredo-do-arquivo\n"), 0o600); err != nil {
t.Fatal(err)
}
cfg, err := load(env(map[string]string{
"BP_DB_USER": "botpontos_app",
"BP_DB_PASSWORD_FILE": path,
}))
if err != nil {
t.Fatalf("erro inesperado: %v", err)
}
if cfg.DB.Password != "segredo-do-arquivo" {
t.Errorf("senha = %q, esperado sem quebra de linha", cfg.DB.Password)
}
}
func TestLoadMissingSecretFile(t *testing.T) {
_, err := load(env(map[string]string{
"BP_DB_USER": "botpontos_app",
"BP_DB_PASSWORD_FILE": filepath.Join(t.TempDir(), "nao-existe"),
}))
if err == nil || !strings.Contains(err.Error(), "BP_DB_PASSWORD_FILE") {
t.Fatalf("esperado erro de arquivo de segredo, veio: %v", err)
}
}
func TestLoadInvalidValues(t *testing.T) {
_, err := load(env(map[string]string{
"BP_LOG_LEVEL": "verboso",
"BP_DISPATCH_INTERVAL": "abc",
"BP_DB_PORT": "porta",
"BP_DEFAULT_TIMEZONE": "Lugar/Inexistente",
}))
if err == nil {
t.Fatal("esperado erro de validação")
}
for _, expected := range []string{
"BP_LOG_LEVEL",
"BP_DISPATCH_INTERVAL",
"BP_DB_PORT",
"BP_DEFAULT_TIMEZONE",
"BP_DB_USER",
"BP_DB_PASSWORD",
} {
if !strings.Contains(err.Error(), expected) {
t.Errorf("erro deveria citar %s: %v", expected, err)
}
}
}
func TestDSNEscapesPassword(t *testing.T) {
db := DB{Host: "postgres", Port: 5432, Name: "botpontos", User: "app", Password: "p@ss/w:rd?#"}
parsed, err := url.Parse(db.DSN())
if err != nil {
t.Fatalf("DSN inválido: %v", err)
}
password, _ := parsed.User.Password()
if password != db.Password {
t.Errorf("senha = %q, esperado %q", password, db.Password)
}
if parsed.Query().Get("sslmode") != "disable" {
t.Errorf("sslmode inesperado: %s", parsed.RawQuery)
}
}