package flow import ( "context" "os" "testing" "github.com/gogf/gf/v2/frame/g" ) // TestRedisLockMutualExclusion 验证互斥与防误删(需 AI_AGENT_TEST_REDIS=1 且本地 Redis 可用) func TestRedisLockMutualExclusion(t *testing.T) { if os.Getenv("AI_AGENT_TEST_REDIS") != "1" { t.Skip("skip: AI_AGENT_TEST_REDIS not set") } ctx := context.Background() key := "workflow:exec:recover:test-lock" // 清理残留 g.Redis().Del(ctx, key) l1 := NewRedisLock(key, 60) l2 := NewRedisLock(key, 60) ok1, err := l1.Acquire(ctx) if err != nil || !ok1 { t.Fatalf("l1 acquire should succeed: ok=%v err=%v", ok1, err) } ok2, err := l2.Acquire(ctx) if err != nil { t.Fatalf("l2 acquire err: %v", err) } if ok2 { t.Fatalf("l2 不应抢到已被 l1 持有的锁") } // l2 尝试释放 l1 的锁:token 不匹配,不应删除 if err := l2.Release(ctx); err != nil { t.Fatalf("l2 release err: %v", err) } ok2, _ = l2.Acquire(ctx) if ok2 { t.Fatalf("l2 释放他人锁后不应能抢到(l1 锁应仍在)") } // l1 释放后 l2 可抢到 if err := l1.Release(ctx); err != nil { t.Fatalf("l1 release err: %v", err) } ok2, err = l2.Acquire(ctx) if err != nil || !ok2 { t.Fatalf("l1 释放后 l2 应可抢到: ok=%v err=%v", ok2, err) } l2.Release(ctx) g.Redis().Del(ctx, key) }