package migration import ( "context" "path/filepath" "testing" "cmroubao/backend-api/internal/platform/database" ) func TestRunnerSupportsUpStatusDownAndIdempotentUp(t *testing.T) { db, err := database.Open( context.Background(), filepath.Join(t.TempDir(), "migration.db"), ) if err != nil { t.Fatalf("database.Open() error = %v", err) } t.Cleanup(func() { _ = db.Close() }) runner, err := New(db) if err != nil { t.Fatalf("New() error = %v", err) } applied, err := runner.Up(context.Background()) if err != nil { t.Fatalf("Up() error = %v", err) } if applied != 9 { t.Fatalf("Up() applied = %d, want 9", applied) } assertStatuses(t, runner, map[int64]bool{ 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, }) applied, err = runner.Up(context.Background()) if err != nil { t.Fatalf("second Up() error = %v", err) } if applied != 0 { t.Fatalf("second Up() applied = %d, want 0", applied) } if err := runner.Down(context.Background()); err != nil { t.Fatalf("Down() error = %v", err) } assertStatuses(t, runner, map[int64]bool{ 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: false, }) applied, err = runner.Up(context.Background()) if err != nil { t.Fatalf("final Up() error = %v", err) } if applied != 1 { t.Fatalf("final Up() applied = %d, want 1", applied) } assertStatuses(t, runner, map[int64]bool{ 1: true, 2: true, 3: true, 4: true, 5: true, 6: true, 7: true, 8: true, 9: true, }) } func assertStatuses( t *testing.T, runner *Runner, want map[int64]bool, ) { t.Helper() statuses, err := runner.Status(context.Background()) if err != nil { t.Fatalf("Status() error = %v", err) } if len(statuses) != len(want) { t.Fatalf("Status() count = %d, want %d", len(statuses), len(want)) } for _, status := range statuses { applied, ok := want[status.Version] if !ok { t.Fatalf("unexpected migration status = %+v", status) } if status.Applied != applied { t.Fatalf( "migration %d applied = %t, want %t", status.Version, status.Applied, applied, ) } } }