返回 DeepSeek-Reasonix
draft_runtime_test.go
根目录 / desktop / draft_runtime_test.go
1 package main
2
3 import (
4 "encoding/json"
5 "path/filepath"
6 "reasonix/desktop/internal/draftstate"
7 "reasonix/internal/config"
8 "reasonix/internal/control"
9 "testing"
10 )
11
12 func TestDraftRetryRebuildsCanonicalControllerAndPreservesFailedCandidate(t *testing.T) {
13 a, tab, old, _ := auditMigratedTab(t)
14 cfg, err := config.LoadForRootReadOnly(tab.WorkspaceRoot)
15 if err != nil {
16 t.Fatal(err)
17 }
18 for i := range cfg.Providers {
19 if cfg.Providers[i].Name == "new" {
20 cfg.Providers[i].SupportedEfforts = []string{"low", "high"}
21 cfg.Providers[i].DefaultEffort = "low"
22 }
23 }
24 if err := cfg.SaveTo(config.UserConfigPath()); err != nil {
25 t.Fatal(err)
26 }
27 a.desktopDrafts = draftstate.New(filepath.Join(t.TempDir(), "drafts.sqlite"))
28 t.Cleanup(func() { _ = a.desktopDrafts.Close(); tab.Ctrl.Close() })
29 _, op := beginDraftTestOperation(t, a, "starting")
30 // Bind the fixture operation to the already canonical session, as a retry
31 // does after the first Controller has become ready but admission failed.
32 op.SessionID = tab.SessionID
33 identity := tab.SessionID
34 settings := SessionDraftSettings{Model: "new/new-model", Effort: "high", ToolApprovalMode: "read-only", CollaborationMode: "plan", DisabledMCP: map[string]ServerView{"unused": {Name: "unused"}}, MCPOrder: []string{"unused"}}
35 if err := a.prepareDraftRuntime(op, settings); err != nil {
36 t.Fatal(err)
37 }
38 if tab.Ctrl == old || tab.SessionID != identity {
39 t.Fatal("retry did not replace the graph on the same Session")
40 }
41 if err := a.verifyDraftRuntime(tab.ID, settings); err != nil {
42 t.Fatal(err)
43 }
44 current := tab.Ctrl
45 settings.Model = "removed/model"
46 if err := a.prepareDraftRuntime(op, settings); err == nil {
47 t.Fatal("missing model accepted")
48 }
49 if tab.Ctrl != current || tab.SessionID != identity {
50 t.Fatal("failed candidate replaced the execution owner")
51 }
52 }
53
54 func TestDraftCancelWaitsForWorkerOwnership(t *testing.T) {
55 isolateDesktopUserDirs(t)
56 a := newDraftTestApp(t)
57 _, op := beginDraftTestOperation(t, a, "starting")
58 release, err := a.draftStore().WorkerLease(op.SessionID)
59 if err != nil {
60 t.Fatal(err)
61 }
62 defer release()
63 view, err := a.CancelDraftSubmission(op.ID)
64 if err != nil {
65 t.Fatal(err)
66 }
67 if view.Phase != "cancel_requested" || view.CanEdit || view.CanResume {
68 t.Fatalf("cancel unlocked live worker: %+v", view)
69 }
70 if unlock, err := a.lockDraftRuntimePublication(op.ID); err == nil {
71 unlock()
72 t.Fatal("cancelled worker can publish a runtime")
73 }
74 a.finishDraftCancellation(op)
75 view, err = a.GetDraftSubmission(op.ID)
76 if err != nil || view.Phase != "cancelled" {
77 t.Fatalf("worker finish: %+v %v", view, err)
78 }
79 }
80
81 func TestDraftV3SnapshotSurvivesV5DatabaseAndChangedEditor(t *testing.T) {
82 a := newDraftTestApp(t)
83 draft, op := beginDraftTestOperation(t, a, "reserved")
84 request := SessionDraftSubmissionRequest{SnapshotVersion: 3, Settings: SessionDraftSettings{Model: "frozen/model", ToolApprovalMode: "read-only"}}
85 encoded, err := json.Marshal(request)
86 if err != nil {
87 t.Fatal(err)
88 }
89 op.RequestJSON = string(encoded)
90 settings, err := a.draftOperationSettings(op)
91 if err != nil || settings.Model != "frozen/model" {
92 t.Fatalf("frozen settings: %+v %v (draft %s)", settings, err, draft.ID)
93 }
94 request.SnapshotVersion = draftstate.SnapshotVersion + 1
95 encoded, _ = json.Marshal(request)
96 op.RequestJSON = string(encoded)
97 if _, err = a.draftOperationSettings(op); err == nil {
98 t.Fatal("future snapshot was interpreted as current editor settings")
99 }
100 }
101
102 func TestDraftV5InheritedModelSnapshotRemainsFrozenForRetry(t *testing.T) {
103 a := newDraftTestApp(t)
104 _, op := beginDraftTestOperation(t, a, "reserved")
105 request := SessionDraftSubmissionRequest{
106 SnapshotVersion: draftstate.SnapshotVersion,
107 Settings: SessionDraftSettings{
108 Model: "fixture/frozen", ModelSource: draftModelSourceDefault, ToolApprovalMode: "read-only",
109 },
110 }
111 encoded, err := json.Marshal(request)
112 if err != nil {
113 t.Fatal(err)
114 }
115 op.RequestJSON = string(encoded)
116 settings, err := a.draftOperationSettings(op)
117 if err != nil {
118 t.Fatal(err)
119 }
120 if settings.Model != "fixture/frozen" || settings.ModelSource != draftModelSourceDefault {
121 t.Fatalf("retry settings = %+v, want the submission-time effective model", settings)
122 }
123 }
124
125 func TestDraftRetryChangesActualReadyControllerPermission(t *testing.T) {
126 isolateDesktopUserDirs(t)
127 a := newDraftTestApp(t)
128 _, op := beginDraftTestOperation(t, a, "starting")
129 ctrl := newFixtureController(t, control.Options{ModelRef: "fixture/model"})
130 ctrl.SetToolApprovalMode(control.ToolApprovalDangerFullAccess)
131 tab := &WorkspaceTab{ID: "tab", SessionID: op.SessionID, Ctrl: ctrl, model: "fixture/model", toolApprovalMode: control.ToolApprovalDangerFullAccess}
132 a.tabs[tab.ID] = tab
133 a.tabOrder = []string{tab.ID}
134 settings := SessionDraftSettings{Model: "fixture/model", ToolApprovalMode: "read-only", CollaborationMode: "plan"}
135 if err := a.prepareDraftRuntime(op, settings); err != nil {
136 t.Fatal(err)
137 }
138 if ctrl.ToolApprovalMode() != normalizeToolApprovalMode(settings.ToolApprovalMode) || !ctrl.PlanMode() {
139 t.Fatalf("actual runtime retained permission=%s plan=%v", ctrl.ToolApprovalMode(), ctrl.PlanMode())
140 }
141 if err := a.verifyDraftRuntime(tab.ID, settings); err != nil {
142 t.Fatal(err)
143 }
144 }
145
145 lines GO