返回 DeepSeek-Reasonix
subagent_cleanup_recovery_test.go
根目录 / internal / boot / subagent_cleanup_recovery_test.go
1 package boot
2
3 import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 "reasonix/internal/agent"
9 "reasonix/internal/tool"
10 )
11
12 func prepareRunningSubagent(t *testing.T, sessionDir string) string {
13 t.Helper()
14 store := agent.NewSubagentStore(filepath.Join(sessionDir, "subagents"))
15 spec := agent.SubagentSpec{
16 Kind: "task",
17 Name: "task",
18 WorkspaceRoot: t.TempDir(),
19 ParentSession: "parent-session",
20 SystemPrompt: "sys",
21 Registry: tool.NewRegistry(),
22 Model: "base-model",
23 }
24 run, err := store.PrepareFresh(spec)
25 if err != nil {
26 t.Fatalf("PrepareFresh: %v", err)
27 }
28 if err := store.MarkRunning(run); err != nil {
29 t.Fatalf("MarkRunning: %v", err)
30 }
31 ref := run.Ref
32 run.Release()
33 return ref
34 }
35
36 func requireSubagentStatus(t *testing.T, sessionDir, ref string, want agent.SubagentStatus) {
37 t.Helper()
38 meta, err := agent.NewSubagentStore(filepath.Join(sessionDir, "subagents")).LoadMeta(ref)
39 if err != nil {
40 t.Fatalf("LoadMeta(%s): %v", ref, err)
41 }
42 if meta.Status != want {
43 t.Fatalf("status = %q, want %q", meta.Status, want)
44 }
45 }
46
47 func TestNewSubagentStoreCleansStaleRunningOnEveryBuild(t *testing.T) {
48 sessionDir := t.TempDir()
49
50 firstRef := prepareRunningSubagent(t, sessionDir)
51 if _, err := newSubagentStore(sessionDir, nil); err != nil {
52 t.Fatalf("newSubagentStore (first): %v", err)
53 }
54 requireSubagentStatus(t, sessionDir, firstRef, agent.SubagentInterrupted)
55
56 secondRef := prepareRunningSubagent(t, sessionDir)
57 if _, err := newSubagentStore(sessionDir, nil); err != nil {
58 t.Fatalf("newSubagentStore (second): %v", err)
59 }
60 requireSubagentStatus(t, sessionDir, secondRef, agent.SubagentInterrupted)
61 }
62
63 func TestNewSubagentStoreParentProbeDefersThenRecovers(t *testing.T) {
64 sessionDir := t.TempDir()
65 ref := prepareRunningSubagent(t, sessionDir)
66 parentPath := filepath.Join(sessionDir, "parent-session.jsonl")
67
68 if _, err := newSubagentStore(sessionDir, func(path string) bool {
69 return filepath.Clean(path) == filepath.Clean(parentPath)
70 }); err != nil {
71 t.Fatalf("newSubagentStore (live parent): %v", err)
72 }
73 requireSubagentStatus(t, sessionDir, ref, agent.SubagentRunning)
74
75 if _, err := newSubagentStore(sessionDir, func(string) bool { return false }); err != nil {
76 t.Fatalf("newSubagentStore (dead parent): %v", err)
77 }
78 requireSubagentStatus(t, sessionDir, ref, agent.SubagentInterrupted)
79 }
80
81 func TestNewSubagentStoreNeverCachesCleanupError(t *testing.T) {
82 sessionDir := t.TempDir()
83 if err := os.WriteFile(filepath.Join(sessionDir, "subagents"), []byte("not a directory"), 0o600); err != nil {
84 t.Fatalf("WriteFile: %v", err)
85 }
86
87 for attempt := 1; attempt <= 2; attempt++ {
88 if _, err := newSubagentStore(sessionDir, nil); err == nil {
89 t.Fatalf("newSubagentStore attempt %d unexpectedly succeeded", attempt)
90 }
91 }
92 }
93
93 lines GO