package store import ( "errors" "testing" "gorm.io/gorm" ) // 版本化 runner:首次跑全部、再跑全跳过、追加只跑新步。 func TestRunVersionedMigrations_RunsOnceThenSkips(t *testing.T) { p := newTestStore(t) var ran []int steps := []migrationStep{ {1, "a", func(*gorm.DB) error { ran = append(ran, 1); return nil }}, {2, "b", func(*gorm.DB) error { ran = append(ran, 2); return nil }}, } if err := runVersionedMigrations(p.db, steps); err != nil { t.Fatal(err) } if len(ran) != 2 { t.Fatalf("首次应跑 2 步,得 %v", ran) } ran = nil if err := runVersionedMigrations(p.db, steps); err != nil { t.Fatal(err) } if len(ran) != 0 { t.Fatalf("第二次应全跳过(已记录),得 %v", ran) } steps = append(steps, migrationStep{3, "c", func(*gorm.DB) error { ran = append(ran, 3); return nil }}) if err := runVersionedMigrations(p.db, steps); err != nil { t.Fatal(err) } if len(ran) != 1 || ran[0] != 3 { t.Fatalf("应只跑新增步骤 #3,得 %v", ran) } } // 某步失败即停:后续步骤不跑,且失败步骤不记录(下次从它重试);已成功步骤不重跑。 func TestRunVersionedMigrations_StopsOnFailure(t *testing.T) { p := newTestStore(t) var ran []int steps := []migrationStep{ {1, "ok", func(*gorm.DB) error { ran = append(ran, 1); return nil }}, {2, "boom", func(*gorm.DB) error { return errors.New("boom") }}, {3, "after", func(*gorm.DB) error { ran = append(ran, 3); return nil }}, } if err := runVersionedMigrations(p.db, steps); err == nil { t.Fatal("步骤 #2 失败应返回 error") } if len(ran) != 1 { t.Fatalf("步骤 #3 不该在 #2 失败后跑,得 %v", ran) } // 重试:#1 已记录跳过(不重复跑),#2 再次失败即停。 ran = nil if err := runVersionedMigrations(p.db, steps); err == nil { t.Fatal("重试仍应在 #2 失败") } if len(ran) != 0 { t.Fatalf("已应用的 #1 不该重跑,得 %v", ran) } }