返回 DeepSeek-Reasonix
inbox_queue_test.go
根目录 / internal / control / inbox_queue_test.go
1 package control
2
3 import (
4 "path/filepath"
5 "strings"
6 "testing"
7
8 "reasonix/internal/event"
9 "reasonix/internal/sessioninbox"
10 )
11
12 func TestInboxQueueFullBodySavePreservesEnvelopeAndSession(t *testing.T) {
13 dir := t.TempDir()
14 path := filepath.Join(dir, "first.jsonl")
15 c := newOwnedTestController(t, Options{SessionDir: dir, SessionPath: path, Sink: event.Discard})
16 defer c.Close()
17 if err := c.SetInboxPaused(true); err != nil {
18 t.Fatal(err)
19 }
20 body := strings.Repeat("正文", 150) + "\n尾部"
21 receipt, err := c.EnqueueInbox(InboxRequest{Submit: body, Idempotency: "original"})
22 if err != nil {
23 t.Fatal(err)
24 }
25 st, _ := c.ensureInbox()
26 meta, env, _ := st.ReadItem(receipt.ItemID)
27 env.FrozenRefBlock = "frozen reference bytes"
28 env.Extra = map[string]string{"owned": "keep"}
29 env.Attachments = []string{"report.txt"}
30 if _, err := st.UpdateItemIfVersion(meta.ID, env, sessioninbox.ContentVersion(meta)); err != nil {
31 t.Fatal(err)
32 }
33 read, err := c.InboxQueue(path, InboxQueueRequest{Kind: "read", ItemID: meta.ID})
34 if err != nil || read.Edit == nil || read.Edit.Text != body {
35 t.Fatalf("full read: %+v %v", read, err)
36 }
37 newBody := " " + body + "\n修改 "
38 result, err := c.InboxQueue(path, InboxQueueRequest{Kind: "edit", ItemID: meta.ID, ContentVersion: read.Edit.ContentVersion, Text: newBody})
39 if err != nil || result.Outcome != "applied" {
40 t.Fatalf("save: %+v %v", result, err)
41 }
42 _, saved, _ := st.ReadItem(meta.ID)
43 if saved.SubmitText != newBody || saved.FrozenRefBlock != env.FrozenRefBlock || saved.Extra["owned"] != "keep" || len(saved.Attachments) != 1 || saved.Idempotency != "original" {
44 t.Fatalf("lost envelope: %+v", saved)
45 }
46 if !result.Snapshot.Paused || result.Snapshot.Items[0].ID != meta.ID {
47 t.Fatal("save changed queue policy")
48 }
49 conflict, _ := c.InboxQueue(path, InboxQueueRequest{Kind: "edit", ItemID: meta.ID, ContentVersion: read.Edit.ContentVersion, Text: "stale"})
50 if conflict.Reason != "content_changed" {
51 t.Fatal(conflict)
52 }
53 c.SetSessionPath(filepath.Join(dir, "second.jsonl"))
54 stale, err := c.InboxQueue(path, InboxQueueRequest{Kind: "pause", Paused: true})
55 if err != nil || stale.Reason != "session_changed" || stale.Snapshot.SessionPath != "" {
56 t.Fatalf("wrong-session result: %+v %v", stale, err)
57 }
58 }
59
60 func TestInboxQueueDispatchExecutesSavedTextInMovedOrder(t *testing.T) {
61 c, runner, done := newInboxDispatchController(t)
62 if err := c.SetInboxPaused(true); err != nil {
63 t.Fatal(err)
64 }
65 a, err := c.EnqueueInbox(InboxRequest{Submit: "first"})
66 if err != nil {
67 t.Fatal(err)
68 }
69 b, err := c.EnqueueInbox(InboxRequest{Submit: "second"})
70 if err != nil {
71 t.Fatal(err)
72 }
73 path := c.SessionPath()
74 read, _ := c.InboxQueue(path, InboxQueueRequest{Kind: "read", ItemID: b.ItemID})
75 saved, err := c.InboxQueue(path, InboxQueueRequest{Kind: "edit", ItemID: b.ItemID, Text: "second edited", ContentVersion: read.Edit.ContentVersion})
76 if err != nil || saved.Outcome != "applied" {
77 t.Fatalf("save: %+v %v", saved, err)
78 }
79 moved, err := c.InboxQueue(path, InboxQueueRequest{Kind: "move", ItemID: b.ItemID, BeforeItemID: &a.ItemID, QueueRevision: saved.Snapshot.Revision})
80 if err != nil || moved.Outcome != "applied" {
81 t.Fatalf("move: %+v %v", moved, err)
82 }
83 if err := c.SetInboxPaused(false); err != nil {
84 t.Fatal(err)
85 }
86 if got := waitForInboxDispatch(t, c, runner); got != "second edited" {
87 t.Fatalf("first dispatched %q", got)
88 }
89 waitForInboxTurnDone(t, c, done)
90 if got := waitForInboxDispatch(t, c, runner); got != "first" {
91 t.Fatalf("second dispatched %q", got)
92 }
93 waitForInboxTurnDone(t, c, done)
94 }
95
95 lines GO