Scert/backend/internal/database/mysql_task_validation_migration_test.go
xuans 24a9683c43 保存证书校验后台任务及独立结果的修复前基线
校验结果事务持久化、三库迁移及前端详情接线已实现,完整回归仍在执行。审查发现前端校验幂等键包含路径分隔符,下一批补回归并修复;本提交不是正式发布或生产验收结论。
2026-10-02 20:25:28 +08:00

68 lines
3.0 KiB
Go

package database
import (
"fmt"
"testing"
)
func TestMySQLRealTaskValidationMigrationRecovery(t *testing.T) {
f := startRealMySQL(t)
baseline := f.database(t)
if err := Migrate(t.Context(), baseline.DB, "mysql"); err != nil {
t.Fatal(err)
}
expectedSchema := mysqlSchemaSnapshot(t, baseline.DB)
const validation = `{"domains":["example.test"],"fingerprint_sha256":"retained-validation"}`
for _, boundary := range []string{"before_create", "after_create", "with_validation"} {
t.Run(boundary, func(t *testing.T) {
db := f.database(t)
mysqlPrepareVersion(t, db.DB, 20)
if boundary != "before_create" {
mysqlDeploymentExec(t, db.DB, mysqlDeploymentStatements(t, 21)[0])
}
if boundary == "with_validation" {
if _, err := db.DB.ExecContext(t.Context(), `INSERT INTO task_validation_results
(task_id, attempt_id, attempt_number, validation_json) VALUES ('validation-task', 'validation-attempt', 1, ?)`, validation); err != nil {
t.Fatal(err)
}
}
mysqlAssertUpgrade(t, db.DB, expectedSchema)
if boundary == "with_validation" {
var stored string
if err := db.DB.QueryRowContext(t.Context(), `SELECT validation_json FROM task_validation_results
WHERE task_id = 'validation-task' AND attempt_id = 'validation-attempt'`).Scan(&stored); err != nil || stored != validation {
t.Fatalf("恢复迁移后校验详情被改写:%v", err)
}
}
})
}
for _, invalid := range []struct{ name, statement string }{
{"short_result", "ALTER TABLE task_validation_results MODIFY COLUMN validation_json TEXT NOT NULL"},
{"wrong_primary_order", "ALTER TABLE task_validation_results DROP PRIMARY KEY, ADD PRIMARY KEY (attempt_id, task_id)"},
{"nullable_attempt", "ALTER TABLE task_validation_results MODIFY COLUMN attempt_number INT NULL"},
{"wrong_engine", "ALTER TABLE task_validation_results ENGINE=MyISAM"},
{"extra_column", "ALTER TABLE task_validation_results ADD COLUMN unexpected INT NOT NULL DEFAULT 0"},
} {
t.Run(invalid.name, func(t *testing.T) {
db := f.database(t)
mysqlPrepareVersion(t, db.DB, 20)
mysqlDeploymentExec(t, db.DB, mysqlDeploymentStatements(t, 21)[0])
if _, err := db.DB.ExecContext(t.Context(), `INSERT INTO task_validation_results
(task_id, attempt_id, attempt_number, validation_json) VALUES ('kept-task', 'kept-attempt', 1, ?)`, validation); err != nil {
t.Fatal(err)
}
mysqlDeploymentExec(t, db.DB, invalid.statement)
before := fmt.Sprint(mysqlSchemaSnapshot(t, db.DB))
assertMySQLDeploymentMigrationRejected(t, db.DB, 20)
if after := fmt.Sprint(mysqlSchemaSnapshot(t, db.DB)); after != before {
t.Fatal("校验结果表冲突不得被自动覆盖或修复")
}
var stored string
if err := db.DB.QueryRowContext(t.Context(), `SELECT validation_json FROM task_validation_results
WHERE task_id = 'kept-task' AND attempt_id = 'kept-attempt'`).Scan(&stored); err != nil || stored != validation {
t.Fatalf("拒绝迁移时不得修改已有校验结果:%v", err)
}
})
}
}