100 lines
2.8 KiB
Go
100 lines
2.8 KiB
Go
package builtin
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"golang.org/x/text/encoding/simplifiedchinese"
|
|
)
|
|
|
|
func encGBK(t *testing.T, s string) []byte {
|
|
t.Helper()
|
|
out, err := simplifiedchinese.GB18030.NewEncoder().String(s)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return []byte(out)
|
|
}
|
|
|
|
func decGBK(t *testing.T, b []byte) string {
|
|
t.Helper()
|
|
out, err := simplifiedchinese.GB18030.NewDecoder().Bytes(b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return string(out)
|
|
}
|
|
|
|
func runEdit(t *testing.T, dir, name, oldS, newS string) {
|
|
t.Helper()
|
|
b, _ := json.Marshal(map[string]any{"path": name, "old_string": oldS, "new_string": newS})
|
|
if _, err := (editFile{workDir: dir}).Execute(context.Background(), b); err != nil {
|
|
t.Fatalf("edit_file: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestEditFileCRLFGBKPreservesEncodingAndEndings(t *testing.T) {
|
|
dir := t.TempDir()
|
|
src := "第一行 hello\r\n第二行 world\r\n第三行 done\r\n"
|
|
if err := os.WriteFile(filepath.Join(dir, "f.cs"), encGBK(t, src), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// old/new arrive LF-only, as the model copies them out of read_file output.
|
|
runEdit(t, dir, "f.cs", "第一行 hello\n第二行 world", "第一行 HELLO\n第二行 WORLD")
|
|
|
|
raw, err := os.ReadFile(filepath.Join(dir, "f.cs"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
got := decGBK(t, raw)
|
|
want := "第一行 HELLO\r\n第二行 WORLD\r\n第三行 done\r\n"
|
|
if got != want {
|
|
t.Fatalf("content/endings not preserved:\n got %q\nwant %q", got, want)
|
|
}
|
|
if strings.Contains(strings.ReplaceAll(got, "\r\n", ""), "\n") {
|
|
t.Fatalf("a bare \\n leaked into a CRLF file: %q", got)
|
|
}
|
|
}
|
|
|
|
func TestEditFileLFStaysLF(t *testing.T) {
|
|
dir := t.TempDir()
|
|
if err := os.WriteFile(filepath.Join(dir, "f.txt"), []byte("alpha\nbeta\ngamma\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
runEdit(t, dir, "f.txt", "alpha\nbeta", "ALPHA\nBETA")
|
|
raw, _ := os.ReadFile(filepath.Join(dir, "f.txt"))
|
|
if strings.Contains(string(raw), "\r") {
|
|
t.Fatalf("CR leaked into an LF file: %q", string(raw))
|
|
}
|
|
if string(raw) != "ALPHA\nBETA\ngamma\n" {
|
|
t.Fatalf("unexpected result: %q", string(raw))
|
|
}
|
|
}
|
|
|
|
func TestMultiEditCRLF(t *testing.T) {
|
|
dir := t.TempDir()
|
|
src := "one\r\ntwo\r\nthree\r\nfour\r\n"
|
|
if err := os.WriteFile(filepath.Join(dir, "f.txt"), []byte(src), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
b, _ := json.Marshal(map[string]any{
|
|
"path": "f.txt",
|
|
"edits": []map[string]any{
|
|
{"old_string": "one\ntwo", "new_string": "ONE\nTWO"},
|
|
{"old_string": "three", "new_string": "THREE"},
|
|
},
|
|
})
|
|
if _, err := (multiEdit{workDir: dir}).Execute(context.Background(), b); err != nil {
|
|
t.Fatalf("multi_edit: %v", err)
|
|
}
|
|
raw, _ := os.ReadFile(filepath.Join(dir, "f.txt"))
|
|
if string(raw) != "ONE\r\nTWO\r\nTHREE\r\nfour\r\n" {
|
|
t.Fatalf("multi_edit mangled endings: %q", string(raw))
|
|
}
|
|
}
|