diff --git a/backend-java/src/test/java/com/nanri/aiimage/config/FlywayMigrationDrillDocTest.java b/backend-java/src/test/java/com/nanri/aiimage/config/FlywayMigrationDrillDocTest.java new file mode 100644 index 00000000..da6f9306 --- /dev/null +++ b/backend-java/src/test/java/com/nanri/aiimage/config/FlywayMigrationDrillDocTest.java @@ -0,0 +1,66 @@ +package com.nanri.aiimage.config; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * task-201:迁移演练 runbook 契约。 + * docs/flyway-migration-drill.md 固化演练步骤:干净迁移/validate/验证 SQL/回滚/锁窗口/校验和/ + * 幂等重跑/不动历史;on-DB 步骤由运维在副本库按 runbook 执行(本环境无库)。 + */ +class FlywayMigrationDrillDocTest { + + private static final String DOC = "docs/flyway-migration-drill.md"; + + private String doc() throws IOException { + return Files.readString(Path.of(System.getProperty("user.dir"), DOC)); + } + + @Test + void drillDocExists() { + assertTrue(Files.exists(Path.of(System.getProperty("user.dir"), DOC)), "演练 runbook 应存在"); + } + + @Test + void cleanMigrateStepDescribed() throws IOException { + assertTrue(doc().contains("migrate"), "应描述干净迁移步骤"); + } + + @Test + void validateStepDescribed() throws IOException { + assertTrue(doc().contains("validate"), "应包含 validate 校验历史 checksum 步骤"); + } + + @Test + void validationSqlStepDescribed() throws IOException { + assertTrue(doc().contains("验证 SQL"), "应包含验证 SQL 步骤"); + } + + @Test + void rollbackStepDescribed() throws IOException { + assertTrue(doc().contains("回滚"), "应包含回滚验证步骤"); + } + + @Test + void lockWindowEstimatedStepDescribed() throws IOException { + assertTrue(doc().contains("锁窗口"), "应包含锁窗口估算步骤"); + } + + @Test + void checksumAndIdempotentRerunDescribed() throws IOException { + String text = doc(); + assertTrue(text.contains("checksum") || text.contains("校验和"), "应包含校验和检查"); + assertTrue(text.contains("幂等重跑") || text.contains("idempotent"), "应包含幂等重跑"); + } + + @Test + void noLegacyTouchGuarded() throws IOException { + assertTrue(doc().contains("历史") && (doc().contains("未被动") || doc().contains("未被改动")), + "应明确演练不动历史迁移"); + } +}