返回 DeepSeek-Reasonix
fixture_test.go
根目录 / internal / autoresearch / fixture_test.go
1 package autoresearch
2
3 import (
4 "encoding/json"
5 "os"
6 "path/filepath"
7 "testing"
8 "time"
9 )
10
11 // writeArchiveFixture materializes a historical task directory for read-only
12 // tests. Production code never creates archives.
13 func writeArchiveFixture(t *testing.T, workspaceRoot, taskID, goal string, criteria []SuccessCriterion) string {
14 t.Helper()
15 if resolved, err := filepath.EvalSymlinks(workspaceRoot); err == nil {
16 workspaceRoot = resolved
17 }
18 root := filepath.Join(workspaceRoot, ".reasonix", "autoresearch", taskID)
19 state := filepath.Join(root, "state")
20 logs := filepath.Join(root, "logs")
21 if err := os.MkdirAll(state, 0o755); err != nil {
22 t.Fatalf("mkdir state: %v", err)
23 }
24 if err := os.MkdirAll(logs, 0o755); err != nil {
25 t.Fatalf("mkdir logs: %v", err)
26 }
27 if criteria == nil {
28 criteria = []SuccessCriterion{}
29 }
30 spec := TaskSpec{
31 TaskID: taskID,
32 Goal: goal,
33 AllowedOperations: AllowedOperations{
34 Write: true,
35 },
36 SuccessCriteria: criteria,
37 }
38 writeJSON(t, filepath.Join(state, "task_spec.json"), spec)
39 writeJSON(t, filepath.Join(state, "progress.json"), Progress{
40 Status: StatusRunning,
41 UpdatedAt: time.Date(2026, 6, 30, 10, 0, 0, 0, time.UTC),
42 })
43 if err := os.WriteFile(filepath.Join(state, "directions_tried.json"), []byte("[]\n"), 0o644); err != nil {
44 t.Fatalf("write directions: %v", err)
45 }
46 if err := os.WriteFile(filepath.Join(state, "findings.jsonl"), nil, 0o644); err != nil {
47 t.Fatalf("write findings: %v", err)
48 }
49 if err := os.WriteFile(filepath.Join(state, "iteration_log.jsonl"), nil, 0o644); err != nil {
50 t.Fatalf("write iteration log: %v", err)
51 }
52 if err := os.WriteFile(filepath.Join(logs, "heartbeat.jsonl"), nil, 0o644); err != nil {
53 t.Fatalf("write heartbeat: %v", err)
54 }
55 return root
56 }
57
58 func writeJSON(t *testing.T, path string, v any) {
59 t.Helper()
60 data, err := json.MarshalIndent(v, "", " ")
61 if err != nil {
62 t.Fatalf("marshal %s: %v", path, err)
63 }
64 if err := os.WriteFile(path, append(data, '\n'), 0o644); err != nil {
65 t.Fatalf("write %s: %v", path, err)
66 }
67 }
68
69 func appendFindingLine(t *testing.T, taskRoot string, f Finding) {
70 t.Helper()
71 data, err := json.Marshal(f)
72 if err != nil {
73 t.Fatalf("marshal finding: %v", err)
74 }
75 path := filepath.Join(taskRoot, "state", "findings.jsonl")
76 fhandle, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
77 if err != nil {
78 t.Fatalf("open findings: %v", err)
79 }
80 defer fhandle.Close()
81 if _, err := fhandle.Write(append(data, '\n')); err != nil {
82 t.Fatalf("append finding: %v", err)
83 }
84 }
85
86 func writeProgress(t *testing.T, taskRoot string, progress Progress) {
87 t.Helper()
88 writeJSON(t, filepath.Join(taskRoot, "state", "progress.json"), progress)
89 }
90
91 func writeDirections(t *testing.T, taskRoot string, directions []DirectionTried) {
92 t.Helper()
93 writeJSON(t, filepath.Join(taskRoot, "state", "directions_tried.json"), directions)
94 }
95
96 func appendHeartbeatLine(t *testing.T, taskRoot string, h Heartbeat) {
97 t.Helper()
98 data, err := json.Marshal(h)
99 if err != nil {
100 t.Fatalf("marshal heartbeat: %v", err)
101 }
102 path := filepath.Join(taskRoot, "logs", "heartbeat.jsonl")
103 fhandle, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
104 if err != nil {
105 t.Fatalf("open heartbeat: %v", err)
106 }
107 defer fhandle.Close()
108 if _, err := fhandle.Write(append(data, '\n')); err != nil {
109 t.Fatalf("append heartbeat: %v", err)
110 }
111 }
112
113 func hashTree(t *testing.T, root string) map[string]string {
114 t.Helper()
115 out := map[string]string{}
116 err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
117 if err != nil {
118 return err
119 }
120 if info.IsDir() {
121 return nil
122 }
123 rel, err := filepath.Rel(root, path)
124 if err != nil {
125 return err
126 }
127 data, err := os.ReadFile(path)
128 if err != nil {
129 return err
130 }
131 out[rel] = string(data)
132 return nil
133 })
134 if err != nil {
135 t.Fatalf("hash tree: %v", err)
136 }
137 return out
138 }
139
140 func modTimes(t *testing.T, root string) map[string]time.Time {
141 t.Helper()
142 out := map[string]time.Time{}
143 err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
144 if err != nil {
145 return err
146 }
147 rel, err := filepath.Rel(root, path)
148 if err != nil {
149 return err
150 }
151 out[rel] = info.ModTime()
152 return nil
153 })
154 if err != nil {
155 t.Fatalf("stat tree: %v", err)
156 }
157 return out
158 }
159
159 lines GO