返回 DeepSeek-Reasonix
quickadd_test.go
根目录 / internal / memory / quickadd_test.go
1 package memory
2
3 import (
4 "os"
5 "path/filepath"
6 "runtime"
7 "strings"
8 "testing"
9 )
10
11 // TestAppendDocCreatesAndAppends verifies the "#" quick-add path: a fresh file
12 // gets a Notes section, and a second note joins the same section rather than
13 // scattering.
14 func TestAppendDocCreatesAndAppends(t *testing.T) {
15 path := filepath.Join(t.TempDir(), "REASONIX.md")
16
17 if err := AppendDoc(path, "first note"); err != nil {
18 t.Fatal(err)
19 }
20 if err := AppendDoc(path, "second note"); err != nil {
21 t.Fatal(err)
22 }
23
24 b, err := os.ReadFile(path)
25 if err != nil {
26 t.Fatal(err)
27 }
28 body := string(b)
29 if strings.Count(body, quickAddHeading) != 1 {
30 t.Fatalf("want exactly one Notes section, got:\n%s", body)
31 }
32 if !strings.Contains(body, "- first note") || !strings.Contains(body, "- second note") {
33 t.Fatalf("notes missing:\n%s", body)
34 }
35 // Order preserved: first before second.
36 if strings.Index(body, "first note") > strings.Index(body, "second note") {
37 t.Fatalf("notes out of order:\n%s", body)
38 }
39 }
40
41 // TestAppendDocPreservesExistingContent verifies a hand-written file keeps its
42 // content and the note lands under a Notes section appended to the end.
43 func TestAppendDocPreservesExistingContent(t *testing.T) {
44 path := filepath.Join(t.TempDir(), "REASONIX.md")
45 original := "# My project\n\nSome existing guidance the user wrote.\n"
46 if err := os.WriteFile(path, []byte(original), 0o644); err != nil {
47 t.Fatal(err)
48 }
49
50 if err := AppendDoc(path, "added via hash"); err != nil {
51 t.Fatal(err)
52 }
53 b, _ := os.ReadFile(path)
54 body := string(b)
55 if !strings.Contains(body, "Some existing guidance the user wrote.") {
56 t.Fatalf("existing content lost:\n%s", body)
57 }
58 if !strings.Contains(body, "- added via hash") {
59 t.Fatalf("note not added:\n%s", body)
60 }
61 }
62
63 // TestAppendDocNormalizesNote ensures a multi-line note can't corrupt the
64 // single-line bullet format.
65 func TestAppendDocNormalizesNote(t *testing.T) {
66 path := filepath.Join(t.TempDir(), "REASONIX.md")
67 if err := AppendDoc(path, "line one\nline two\t with spaces"); err != nil {
68 t.Fatal(err)
69 }
70 b, _ := os.ReadFile(path)
71 body := string(b)
72 if !strings.Contains(body, "- line one line two with spaces") {
73 t.Fatalf("note not normalised to one line:\n%s", body)
74 }
75 }
76
77 func TestAppendDocRejectsSymlinkDestination(t *testing.T) {
78 if runtime.GOOS == "windows" {
79 t.Skip("symlink creation requires elevated privileges on common Windows setups")
80 }
81 outside := filepath.Join(t.TempDir(), "outside.md")
82 if err := os.WriteFile(outside, []byte("keep me"), 0o644); err != nil {
83 t.Fatal(err)
84 }
85 link := filepath.Join(t.TempDir(), "AGENTS.md")
86 if err := os.Symlink(outside, link); err != nil {
87 t.Fatal(err)
88 }
89
90 if err := AppendDoc(link, "must stay local"); err == nil {
91 t.Fatal("AppendDoc followed a symlink destination")
92 }
93 body, err := os.ReadFile(outside)
94 if err != nil {
95 t.Fatal(err)
96 }
97 if string(body) != "keep me" {
98 t.Fatalf("outside target changed to %q", body)
99 }
100 }
101
101 lines GO