Files
Agent-System-Backend/internal/store/surfaces_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

127 lines
4.5 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 (
"testing"
core "git-ssh.u1680832.nyat.app/weichen/Agent-System-Core.git"
)
func testSnapshot(surfaceID, owner, plugin string, base int) core.SurfaceSnapshot {
return core.SurfaceSnapshot{
Identity: core.SurfaceIdentity{SurfaceID: core.ID(surfaceID), Owner: owner, PluginID: plugin, ConversationID: "c1"},
BaseRevision: base,
ActivationEpoch: 1,
Spec: core.SurfaceSpec{Title: "t", Nodes: []core.UINode{{Type: core.UIMarkdown, ID: "n1", Markdown: "x"}}},
}
}
func TestSurfaceSaveCASAndRead(t *testing.T) {
st := openTestStore(t)
// 新建 → revision 1
snap, err := st.SaveSurfaceSnapshot(testSnapshot("s1", "alice", "genui", 0))
if err != nil || snap.Revision != 1 {
t.Fatalf("create: rev=%d err=%v", snap.Revision, err)
}
// 基于最新版的更新 → revision 2
snap2, err := st.SaveSurfaceSnapshot(testSnapshot("s1", "alice", "genui", 1))
if err != nil || snap2.Revision != 2 {
t.Fatalf("update: rev=%d err=%v", snap2.Revision, err)
}
// 过期 base → 冲突并携带当前版本
_, err = st.SaveSurfaceSnapshot(testSnapshot("s1", "alice", "genui", 1))
var conflict *ErrRevisionConflict
if err == nil {
t.Fatal("stale base should conflict")
}
if e, ok := err.(*ErrRevisionConflict); !ok {
t.Fatalf("want ErrRevisionConflict, got %v", err)
} else if e.Current != 2 {
t.Fatalf("conflict should carry current=2, got %d", e.Current)
}
_ = conflict
// owner 隔离:bob 读不到 alice 的页面
if _, err := st.GetSurfaceSnapshot("bob", "s1", 0); err != ErrNotFound {
t.Fatalf("cross-owner read should be NotFound, got %v", err)
}
// 跨 owner 写同 id → 冲突(surface 已存在且非本 owner 视为冲突路径)
if _, err := st.SaveSurfaceSnapshot(testSnapshot("s1", "bob", "genui", 0)); err == nil {
t.Fatal("cross-owner create on existing id should fail")
}
// 读取往返:字段保真
got, err := st.GetSurfaceSnapshot("alice", "s1", 0)
if err != nil || got.Revision != 2 || got.Spec.Title != "t" || len(got.Spec.Nodes) != 1 {
t.Fatalf("read-back mismatch: %+v err=%v", got, err)
}
old, err := st.GetSurfaceSnapshot("alice", "s1", 1)
if err != nil || old.Revision != 1 {
t.Fatalf("historical revision read failed: %+v err=%v", old, err)
}
}
func TestSurfaceActivationEpoch(t *testing.T) {
st := openTestStore(t)
// 无行 = 默认关闭(KTD7:不沿用 grants 缺省 true)
a, err := st.GetActivation("alice", "genui")
if err != nil || a.Enabled || a.Epoch != 0 {
t.Fatalf("default should be disabled/epoch0: %+v err=%v", a, err)
}
a1, err := st.SetActivation("alice", "genui", true)
if err != nil || !a1.Enabled || a1.Epoch != 1 {
t.Fatalf("enable: %+v err=%v", a1, err)
}
a2, err := st.SetActivation("alice", "genui", false)
if err != nil || a2.Enabled || a2.Epoch != 2 {
t.Fatalf("disable should bump epoch: %+v err=%v", a2, err)
}
a3, err := st.SetActivation("alice", "genui", true)
if err != nil || a3.Epoch != 3 {
t.Fatalf("re-enable should bump epoch: %+v err=%v", a3, err)
}
// owner 隔离
b, _ := st.GetActivation("bob", "genui")
if b.Enabled || b.Epoch != 0 {
t.Fatalf("bob activation leaked: %+v", b)
}
}
func TestSurfacePendingEvents(t *testing.T) {
st := openTestStore(t)
if _, err := st.SaveSurfaceSnapshot(testSnapshot("s2", "alice", "genui", 0)); err != nil {
t.Fatal(err)
}
if err := st.SetSurfaceEventPending("alice", "s2", 1, true); err != nil {
t.Fatal(err)
}
pend, err := st.ListSurfaceEventsPending(10)
if err != nil || len(pend) != 1 || pend[0].SurfaceID != "s2" || pend[0].Revision != 1 {
t.Fatalf("pending scan: %+v err=%v", pend, err)
}
// owner 校验:他人不能标记/清除
if err := st.SetSurfaceEventPending("bob", "s2", 1, false); err != ErrNotFound {
t.Fatalf("cross-owner pending clear should be NotFound, got %v", err)
}
if err := st.SetSurfaceEventPending("alice", "s2", 1, false); err != nil {
t.Fatal(err)
}
if pend, _ := st.ListSurfaceEventsPending(10); len(pend) != 0 {
t.Fatalf("pending should be cleared: %+v", pend)
}
// 列表投影(含 title 解析)
if _, err := st.SaveSurfaceSnapshot(testSnapshot("s3", "alice", "genui", 0)); err != nil {
t.Fatal(err)
}
metas, err := st.ListSurfaces("alice", "c1")
if err != nil || len(metas) != 2 {
t.Fatalf("list: %+v err=%v", metas, err)
}
for _, m := range metas {
if m.Title != "t" {
t.Fatalf("meta title not parsed: %+v", m)
}
}
other, _ := st.ListSurfaces("alice", "c-other")
if len(other) != 0 {
t.Fatalf("conversation filter broken: %+v", other)
}
}