Files
Agent-System-Backend/internal/store/card_version_test.go
T
weichen f1302ed5b3 Enable canonical versioned Go module consumption
Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements.

Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate.

Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable.

Refs: Versioned dependencies U1/U3; feature/dependency-workspace
2026-10-13 15:47:16 +00:00

98 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package store
import (
"errors"
"sync"
"testing"
"time"
core "git-ssh.u1680832.nyat.app/weichen/Agent-System-Core.git"
)
// 协作存储 U3(KTD7):卡片乐观并发。同版本竞争写入最多一个成功,
// 其余明确 ErrConflict(HTTP 层映射 409);盲写(系统镜像)递增版本。
func newVersionedCard(t *testing.T) (core.ActivityCard, string) {
t.Helper()
return core.ActivityCard{
ID: NewID("card"), Title: "版本卡", Status: core.CardActive,
CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(),
}, "o"
}
func TestCardVersionRoundTrip(t *testing.T) {
st := openTestStore(t)
c, owner := newVersionedCard(t)
if err := st.SaveCard(owner, &c, ""); err != nil {
t.Fatal(err)
}
v, err := st.CardVersion(owner, c.ID)
if err != nil || v != 1 {
t.Fatalf("建卡版本应为 1:v=%d err=%v", v, err)
}
// 乐观更新:expected 一致 → 成功且递增。
if err := st.SaveCardVersioned(owner, &c, "", 1); err != nil {
t.Fatal(err)
}
if v, _ = st.CardVersion(owner, c.ID); v != 2 {
t.Fatalf("版本应递增到 2:%d", v)
}
// 旧版本重放:明确冲突。
err = st.SaveCardVersioned(owner, &c, "", 1)
if !errors.Is(err, ErrConflict) {
t.Fatalf("旧版本应 ErrConflict:%v", err)
}
// 盲写同样递增(系统镜像路径)。
if err := st.SaveCard(owner, &c, ""); err != nil {
t.Fatal(err)
}
if v, _ = st.CardVersion(owner, c.ID); v != 3 {
t.Fatalf("盲写应递增到 3:%d", v)
}
}
// 并发同版本竞争:N 个写者同 expected 提交,恰一个成功,其余 ErrConflict;
// 不存在静默覆盖(R3 验收)。
func TestCardVersionConcurrentSingleWinner(t *testing.T) {
st := openTestStore(t)
c, owner := newVersionedCard(t)
if err := st.SaveCard(owner, &c, ""); err != nil {
t.Fatal(err)
}
const writers = 8
var mu sync.Mutex
ok, conflict := 0, 0
var wg sync.WaitGroup
for i := 0; i < writers; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
dup := c
dup.Title = "并发写"
err := st.SaveCardVersioned(owner, &dup, "", 1)
mu.Lock()
defer mu.Unlock()
switch {
case err == nil:
ok++
case errors.Is(err, ErrConflict):
conflict++
default:
t.Errorf("意外错误:%v", err)
}
}(i)
}
wg.Wait()
if ok != 1 || conflict != writers-1 {
t.Fatalf("应恰一个成功:ok=%d conflict=%d", ok, conflict)
}
if v, _ := st.CardVersion(owner, c.ID); v != 2 {
t.Fatalf("竞争后版本应为 2:%d", v)
}
// cardsvc 读侧:GetCardVersion 返回卡与版本。
_, ver, err := st.GetCardVersion(owner, c.ID)
if err != nil || ver != 2 {
t.Fatalf("GetCardVersion:ver=%d err=%v", ver, err)
}
}