Files
fn_registry/functions/infra/migration_validate_test.go
T
egutierrez ec36278c7b feat: tipos Migration/MigrationStatus y funciones puras migration_parse + migration_validate
Fase 1 del issue 0015. Tipos Go en functions/infra/migration.go con metadata en
types/infra/. Funciones puras: MigrationParse (parsea filename NNN_name.sql +
bloques -- +up/-- +down) y MigrationValidate (verifica secuencia, huecos,
duplicados, bloques vacios). 16 tests, todos pasan.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 02:01:34 +02:00

154 lines
4.3 KiB
Go

package infra
import (
"testing"
)
func makeMig(version int, name, upSQL string) Migration {
return Migration{Version: version, Name: name, UpSQL: upSQL, DownSQL: "DROP TABLE IF EXISTS t;"}
}
func TestMigrationValidate(t *testing.T) {
t.Run("secuencia valida retorna sin errores", func(t *testing.T) {
migrations := []Migration{
makeMig(1, "create_users", "CREATE TABLE users (id TEXT PRIMARY KEY);"),
makeMig(2, "add_email", "ALTER TABLE users ADD COLUMN email TEXT;"),
makeMig(3, "create_roles", "CREATE TABLE roles (id TEXT PRIMARY KEY);"),
}
errs := MigrationValidate(migrations)
if len(errs) != 0 {
t.Errorf("expected no errors, got: %v", errs)
}
})
t.Run("secuencia vacia retorna sin errores", func(t *testing.T) {
errs := MigrationValidate([]Migration{})
if len(errs) != 0 {
t.Errorf("expected no errors for empty slice, got: %v", errs)
}
})
t.Run("version duplicada reporta error", func(t *testing.T) {
migrations := []Migration{
makeMig(1, "create_users", "CREATE TABLE users (id TEXT PRIMARY KEY);"),
makeMig(1, "create_users_dup", "CREATE TABLE users2 (id TEXT PRIMARY KEY);"),
makeMig(2, "add_email", "ALTER TABLE users ADD COLUMN email TEXT;"),
}
errs := MigrationValidate(migrations)
if len(errs) == 0 {
t.Fatal("expected error for duplicate version, got none")
}
found := false
for _, e := range errs {
if containsStr(e, "duplicate") {
found = true
}
}
if !found {
t.Errorf("expected 'duplicate' in errors, got: %v", errs)
}
})
t.Run("hueco en versiones reporta version faltante", func(t *testing.T) {
migrations := []Migration{
makeMig(1, "create_users", "CREATE TABLE users (id TEXT PRIMARY KEY);"),
makeMig(3, "create_roles", "CREATE TABLE roles (id TEXT PRIMARY KEY);"),
}
errs := MigrationValidate(migrations)
if len(errs) == 0 {
t.Fatal("expected error for gap in versions, got none")
}
found := false
for _, e := range errs {
if containsStr(e, "gap") || containsStr(e, "missing 2") {
found = true
}
}
if !found {
t.Errorf("expected gap error in errors, got: %v", errs)
}
})
t.Run("up_sql vacio reporta error", func(t *testing.T) {
migrations := []Migration{
{Version: 1, Name: "create_users", UpSQL: "", DownSQL: "DROP TABLE users;"},
}
errs := MigrationValidate(migrations)
if len(errs) == 0 {
t.Fatal("expected error for empty up_sql, got none")
}
found := false
for _, e := range errs {
if containsStr(e, "empty up_sql") {
found = true
}
}
if !found {
t.Errorf("expected 'empty up_sql' in errors, got: %v", errs)
}
})
t.Run("nombre vacio reporta error", func(t *testing.T) {
migrations := []Migration{
{Version: 1, Name: "", UpSQL: "CREATE TABLE users (id TEXT PRIMARY KEY);"},
}
errs := MigrationValidate(migrations)
if len(errs) == 0 {
t.Fatal("expected error for empty name, got none")
}
found := false
for _, e := range errs {
if containsStr(e, "empty name") {
found = true
}
}
if !found {
t.Errorf("expected 'empty name' in errors, got: %v", errs)
}
})
t.Run("versiones que no empiezan en 1 reportan error", func(t *testing.T) {
migrations := []Migration{
makeMig(2, "create_users", "CREATE TABLE users (id TEXT PRIMARY KEY);"),
makeMig(3, "add_email", "ALTER TABLE users ADD COLUMN email TEXT;"),
}
errs := MigrationValidate(migrations)
if len(errs) == 0 {
t.Fatal("expected error for versions not starting at 1, got none")
}
found := false
for _, e := range errs {
if containsStr(e, "start at 1") {
found = true
}
}
if !found {
t.Errorf("expected 'start at 1' error, got: %v", errs)
}
})
t.Run("multiple errores se reportan todos", func(t *testing.T) {
migrations := []Migration{
{Version: 2, Name: "", UpSQL: ""},
{Version: 4, Name: "something", UpSQL: "CREATE TABLE x (id TEXT);"},
}
errs := MigrationValidate(migrations)
// Expect: not starting at 1, gap between 2 and 4, empty name for v2, empty up_sql for v2
if len(errs) < 3 {
t.Errorf("expected at least 3 errors, got %d: %v", len(errs), errs)
}
})
}
func containsStr(s, sub string) bool {
return len(s) >= len(sub) && (s == sub || len(sub) == 0 ||
func() bool {
for i := 0; i <= len(s)-len(sub); i++ {
if s[i:i+len(sub)] == sub {
return true
}
}
return false
}())
}