package migrate import ( "os" "path/filepath" "runtime" "testing" ) func TestRunMigrationsUpTwice(t *testing.T) { if testing.Short() { t.Skip("skipping integration test in short mode") } databaseURL := os.Getenv("INTEGRATION_DB_URL") if databaseURL == "" { t.Skip("set INTEGRATION_DB_URL to run migration integration tests") } cfg := MigrationConfig{Path: resolveMigrationsPath()} if err := RunMigrationsUp(databaseURL, cfg); err != nil { t.Fatalf("first migrate up: %v", err) } if err := RunMigrationsUp(databaseURL, cfg); err != nil { t.Fatalf("second migrate up: %v", err) } status, err := GetMigrationStatus(databaseURL, cfg) if err != nil { t.Fatalf("get migration status: %v", err) } if status.Dirty { t.Fatalf("expected non-dirty migration status") } if status.Version == 0 { t.Fatalf("expected migration version > 0 after up") } } func resolveMigrationsPath() string { configured := os.Getenv("DB_MIGRATIONS_PATH") if configured == "" { configured = "migrations" } if filepath.IsAbs(configured) { return configured } if len(configured) >= len("file://") && configured[:len("file://")] == "file://" { return configured } if _, err := os.Stat(configured); err == nil { return configured } _, thisFile, _, ok := runtime.Caller(0) if !ok { return configured } moduleRoot := filepath.Clean(filepath.Join(filepath.Dir(thisFile), "..", "..")) candidate := filepath.Join(moduleRoot, configured) if _, err := os.Stat(candidate); err == nil { return candidate } return configured }