返回 DeepSeek-Reasonix
crlf_edit_test.go
根目录 / internal / tool / builtin / crlf_edit_test.go
1 package builtin
2
3 import (
4 "context"
5 "encoding/json"
6 "os"
7 "path/filepath"
8 "strings"
9 "testing"
10
11 "golang.org/x/text/encoding/simplifiedchinese"
12 )
13
14 func encGBK(t *testing.T, s string) []byte {
15 t.Helper()
16 out, err := simplifiedchinese.GB18030.NewEncoder().String(s)
17 if err != nil {
18 t.Fatal(err)
19 }
20 return []byte(out)
21 }
22
23 func decGBK(t *testing.T, b []byte) string {
24 t.Helper()
25 out, err := simplifiedchinese.GB18030.NewDecoder().Bytes(b)
26 if err != nil {
27 t.Fatal(err)
28 }
29 return string(out)
30 }
31
32 func runEdit(t *testing.T, dir, name, oldS, newS string) {
33 t.Helper()
34 b, _ := json.Marshal(map[string]any{"path": name, "old_string": oldS, "new_string": newS})
35 if _, err := (editFile{workDir: dir}).Execute(context.Background(), b); err != nil {
36 t.Fatalf("edit_file: %v", err)
37 }
38 }
39
40 func TestEditFileCRLFGBKPreservesEncodingAndEndings(t *testing.T) {
41 dir := t.TempDir()
42 src := "第一行 hello\r\n第二行 world\r\n第三行 done\r\n"
43 if err := os.WriteFile(filepath.Join(dir, "f.cs"), encGBK(t, src), 0o644); err != nil {
44 t.Fatal(err)
45 }
46
47 // old/new arrive LF-only, as the model copies them out of read_file output.
48 runEdit(t, dir, "f.cs", "第一行 hello\n第二行 world", "第一行 HELLO\n第二行 WORLD")
49
50 raw, err := os.ReadFile(filepath.Join(dir, "f.cs"))
51 if err != nil {
52 t.Fatal(err)
53 }
54 got := decGBK(t, raw)
55 want := "第一行 HELLO\r\n第二行 WORLD\r\n第三行 done\r\n"
56 if got != want {
57 t.Fatalf("content/endings not preserved:\n got %q\nwant %q", got, want)
58 }
59 if strings.Contains(strings.ReplaceAll(got, "\r\n", ""), "\n") {
60 t.Fatalf("a bare \\n leaked into a CRLF file: %q", got)
61 }
62 }
63
64 func TestEditFileLFStaysLF(t *testing.T) {
65 dir := t.TempDir()
66 if err := os.WriteFile(filepath.Join(dir, "f.txt"), []byte("alpha\nbeta\ngamma\n"), 0o644); err != nil {
67 t.Fatal(err)
68 }
69 runEdit(t, dir, "f.txt", "alpha\nbeta", "ALPHA\nBETA")
70 raw, _ := os.ReadFile(filepath.Join(dir, "f.txt"))
71 if strings.Contains(string(raw), "\r") {
72 t.Fatalf("CR leaked into an LF file: %q", string(raw))
73 }
74 if string(raw) != "ALPHA\nBETA\ngamma\n" {
75 t.Fatalf("unexpected result: %q", string(raw))
76 }
77 }
78
79 func TestMultiEditCRLF(t *testing.T) {
80 dir := t.TempDir()
81 src := "one\r\ntwo\r\nthree\r\nfour\r\n"
82 if err := os.WriteFile(filepath.Join(dir, "f.txt"), []byte(src), 0o644); err != nil {
83 t.Fatal(err)
84 }
85 b, _ := json.Marshal(map[string]any{
86 "path": "f.txt",
87 "edits": []map[string]any{
88 {"old_string": "one\ntwo", "new_string": "ONE\nTWO"},
89 {"old_string": "three", "new_string": "THREE"},
90 },
91 })
92 if _, err := (multiEdit{workDir: dir}).Execute(context.Background(), b); err != nil {
93 t.Fatalf("multi_edit: %v", err)
94 }
95 raw, _ := os.ReadFile(filepath.Join(dir, "f.txt"))
96 if string(raw) != "ONE\r\nTWO\r\nTHREE\r\nfour\r\n" {
97 t.Fatalf("multi_edit mangled endings: %q", string(raw))
98 }
99 }
100
100 lines GO