test: 段结果 DAO 补 pgsql 驱动空导入并加软删复活路径验证
单测包不经 main,缺驱动空导入导致 go test ./workflow/dao/flow/ 报 "cannot find database driver for specified database type pgsql"。 新增 TestFlowSegmentResultDaoResurrect:验证 DeleteByExecution 软删后, 对同一 (execution_id, node_id, segment_index) 重新 Save 能否清除 deleted_at 使 ListByNode 再次可见。实测 upsert 的 DO UPDATE SET 子句 不含 deleted_at,段2 不复活 —— 留作失败证据供控制器裁决。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,10 @@ import (
|
||||
"time"
|
||||
|
||||
"gitea.redpowerfuture.com/red-future/common/beans"
|
||||
|
||||
// 空导入:pgsql 驱动。main.go 里已有,但 go test ./workflow/dao/flow/ 单测包不经 main,
|
||||
// 不加则报 "cannot find database driver for specified database type pgsql"
|
||||
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
||||
)
|
||||
|
||||
// TestFlowSegmentResultDao 段结果 DAO 集成测试:Save / ListByNode / DeleteByExecution。
|
||||
@@ -58,3 +62,52 @@ func TestFlowSegmentResultDao(t *testing.T) {
|
||||
t.Fatalf("删除后应无段结果,实际 %d", len(m))
|
||||
}
|
||||
}
|
||||
|
||||
// TestFlowSegmentResultDaoResurrect 软删→重存的"复活"路径验证。
|
||||
// 实体嵌入 beans.SQLBaseDO(含 deleted_at),GoFrame 将其识别为软删除列:
|
||||
// DeleteByExecution 实际执行的是 UPDATE ... SET deleted_at=now(),而非物理 DELETE。
|
||||
// 本测试验证随后对同一 (execution_id, node_id, segment_index) 的 Save(命中
|
||||
// ON CONFLICT ... DO UPDATE)是否会清除 deleted_at,使 ListByNode 再次可见该段。
|
||||
// 若不可见,说明 upsert 的 SET 子句不含 deleted_at,复活路径被破坏 → 续跑复用静默失效。
|
||||
func TestFlowSegmentResultDaoResurrect(t *testing.T) {
|
||||
if os.Getenv("AI_AGENT_TEST_DB") == "" {
|
||||
t.Skip("设置 AI_AGENT_TEST_DB=1 且本地 black_deacon 可用时运行")
|
||||
}
|
||||
ctx := context.WithValue(context.Background(), "user", &beans.User{UserName: "unit_test", TenantId: 999999})
|
||||
execId := time.Now().UnixMilli()
|
||||
nodeId := "seg_test_resurrect"
|
||||
dao := FlowSegmentResultDao
|
||||
|
||||
// 软删即可,物理残留由外部硬清理(docker exec psql DELETE FROM)负责
|
||||
t.Cleanup(func() { _ = dao.DeleteByExecution(ctx, execId) })
|
||||
|
||||
if err := dao.Save(ctx, execId, nodeId, 1, "video_url", "http://host/u1-resurrect.mp4"); err != nil {
|
||||
t.Fatalf("Save 段1失败: %v", err)
|
||||
}
|
||||
if err := dao.Save(ctx, execId, nodeId, 2, "video_url", "http://host/u2-resurrect.mp4"); err != nil {
|
||||
t.Fatalf("Save 段2失败: %v", err)
|
||||
}
|
||||
|
||||
// 软删除整条执行
|
||||
if err := dao.DeleteByExecution(ctx, execId); err != nil {
|
||||
t.Fatalf("DeleteByExecution失败: %v", err)
|
||||
}
|
||||
|
||||
// 重新保存段2(同一 exec/node/idx,不同 URL):
|
||||
// 若 ON CONFLICT DO UPDATE 的 SET 子句不含 deleted_at,段2 在 ListByNode 中仍不可见
|
||||
if err := dao.Save(ctx, execId, nodeId, 2, "video_url", "http://host/u2-resurrect.mp4"); err != nil {
|
||||
t.Fatalf("Save 段2(软删后重存)失败: %v", err)
|
||||
}
|
||||
|
||||
m, err := dao.ListByNode(ctx, execId, nodeId)
|
||||
if err != nil {
|
||||
t.Fatalf("ListByNode失败: %v", err)
|
||||
}
|
||||
// 期望:段2 复活(deleted_at 被 upsert 清除),len(m)==2 且 m[2] 为更新后的 URL
|
||||
if len(m) != 2 {
|
||||
t.Fatalf("软删后重存应复活段2(len=2),实际 len=%d: %+v", len(m), m)
|
||||
}
|
||||
if m[2].URL != "http://host/u2-resurrect.mp4" {
|
||||
t.Fatalf("段2 应恢复为更新后的 URL,实际: %+v", m[2])
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user