207 lines
5.5 KiB
Go
207 lines
5.5 KiB
Go
package sidekick
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestHashLine(t *testing.T) {
|
||
|
|
line := "hello world"
|
||
|
|
h1 := hashLine(line)
|
||
|
|
h2 := hashLine(line)
|
||
|
|
if h1 != h2 {
|
||
|
|
t.Errorf("hashLine is not deterministic: %s != %s", h1, h2)
|
||
|
|
}
|
||
|
|
if len(h1) != 4 {
|
||
|
|
t.Errorf("hashLine output length is not 4: %d", len(h1))
|
||
|
|
}
|
||
|
|
|
||
|
|
h3 := hashLine("hello worle")
|
||
|
|
if h1 == h3 {
|
||
|
|
t.Errorf("hashLine collision for similar strings: %s == %s", h1, h3)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestStripHashlines(t *testing.T) {
|
||
|
|
input := "1:abcd:line 1\n2:ef01:line 2\nnot a hashline\n3:ghij:line 3"
|
||
|
|
// ghij is not valid hex, so it should NOT be stripped if we follow the code strictly
|
||
|
|
// Wait, my code checks for hex: (c >= 'a' && c <= 'f')
|
||
|
|
// So 'ghij' should not be stripped.
|
||
|
|
|
||
|
|
expected := "line 1\nline 2\nnot a hashline\n3:ghij:line 3"
|
||
|
|
got := stripHashlines(input)
|
||
|
|
if got != expected {
|
||
|
|
t.Errorf("stripHashlines failed.\nGot:\n%s\nExpected:\n%s", got, expected)
|
||
|
|
}
|
||
|
|
|
||
|
|
input2 := "10:1234:content with : colons"
|
||
|
|
expected2 := "content with : colons"
|
||
|
|
got2 := stripHashlines(input2)
|
||
|
|
if got2 != expected2 {
|
||
|
|
t.Errorf("stripHashlines failed for content with colons.\nGot: %s\nExpected: %s", got2, expected2)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestEditFileHandler_ExactHashlines(t *testing.T) {
|
||
|
|
tmpFile := "test_edit_exact.txt"
|
||
|
|
initial := "line one\nline two\nline three\nline four"
|
||
|
|
os.WriteFile(tmpFile, []byte(initial), 0644)
|
||
|
|
defer os.Remove(tmpFile)
|
||
|
|
|
||
|
|
h2 := hashLine("line two")
|
||
|
|
h3 := hashLine("line three")
|
||
|
|
|
||
|
|
args := map[string]interface{}{
|
||
|
|
"path": tmpFile,
|
||
|
|
"old_string": "2:" + h2 + ":line two\n3:" + h3 + ":line three",
|
||
|
|
"new_string": "replaced two\nreplaced three",
|
||
|
|
}
|
||
|
|
_, err := editFileHandler(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, _ := os.ReadFile(tmpFile)
|
||
|
|
expected := "line one\nreplaced two\nreplaced three\nline four"
|
||
|
|
if string(got) != expected {
|
||
|
|
t.Errorf("editFileHandler did not precisely replace using hashlines.\nGot: %s\nExpected: %s", string(got), expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGrepFileHandler_Hashlines(t *testing.T) {
|
||
|
|
tmpFile := "test_read_hash.txt"
|
||
|
|
content := "line one\nline two"
|
||
|
|
os.WriteFile(tmpFile, []byte(content), 0644)
|
||
|
|
defer os.Remove(tmpFile)
|
||
|
|
|
||
|
|
args := map[string]interface{}{"path": tmpFile}
|
||
|
|
got, err := readFileHandler(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
lines := strings.Split(got, "\n")
|
||
|
|
if len(lines) != 2 {
|
||
|
|
t.Fatalf("expected 2 lines, got %d", len(lines))
|
||
|
|
}
|
||
|
|
|
||
|
|
if !strings.HasPrefix(lines[0], "1:") || !strings.HasSuffix(lines[0], ":line one") {
|
||
|
|
t.Errorf("line 0 format wrong: %s", lines[0])
|
||
|
|
}
|
||
|
|
if !strings.HasPrefix(lines[1], "2:") || !strings.HasSuffix(lines[1], ":line two") {
|
||
|
|
t.Errorf("line 1 format wrong: %s", lines[1])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestWriteFileHandler_Strip(t *testing.T) {
|
||
|
|
tmpFile := "test_write_strip.txt"
|
||
|
|
defer os.Remove(tmpFile)
|
||
|
|
|
||
|
|
content := "1:abcd:clean line\n2:1234:another line"
|
||
|
|
args := map[string]interface{}{
|
||
|
|
"path": tmpFile,
|
||
|
|
"content": content,
|
||
|
|
}
|
||
|
|
_, err := writeFileHandler(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, _ := os.ReadFile(tmpFile)
|
||
|
|
expected := "clean line\nanother line"
|
||
|
|
if string(got) != expected {
|
||
|
|
t.Errorf("writeFileHandler did not strip hashlines.\nGot: %s\nExpected: %s", string(got), expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestEditFileHandler_Strip(t *testing.T) {
|
||
|
|
tmpFile := "test_edit_strip.txt"
|
||
|
|
initial := "find me\nkeep me"
|
||
|
|
os.WriteFile(tmpFile, []byte(initial), 0644)
|
||
|
|
defer os.Remove(tmpFile)
|
||
|
|
|
||
|
|
args := map[string]interface{}{
|
||
|
|
"path": tmpFile,
|
||
|
|
"old_string": "1:abcd:find me",
|
||
|
|
"new_string": "1:beef:replaced",
|
||
|
|
}
|
||
|
|
_, err := editFileHandler(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
got, _ := os.ReadFile(tmpFile)
|
||
|
|
expected := "replaced\nkeep me"
|
||
|
|
if string(got) != expected {
|
||
|
|
t.Errorf("editFileHandler did not strip hashlines.\nGot: %s\nExpected: %s", string(got), expected)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGrepFileHandler_HashlineAnchors(t *testing.T) {
|
||
|
|
tmpFile := "test_grep_anchors.txt"
|
||
|
|
content := "first line\nsecond line\nthird needle\nfourth line\nfifth needle"
|
||
|
|
os.WriteFile(tmpFile, []byte(content), 0644)
|
||
|
|
defer os.Remove(tmpFile)
|
||
|
|
|
||
|
|
args := map[string]interface{}{
|
||
|
|
"path": tmpFile,
|
||
|
|
"pattern": "needle",
|
||
|
|
"context_lines": 1.0,
|
||
|
|
}
|
||
|
|
got, err := grepFileHandler(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Lines in file:
|
||
|
|
// 1: first line
|
||
|
|
// 2: second line
|
||
|
|
// 3: third needle (MATCH)
|
||
|
|
// 4: fourth line
|
||
|
|
// 5: fifth needle (MATCH)
|
||
|
|
|
||
|
|
// Expected output structure should contain:
|
||
|
|
// --- Match around line 3 ---
|
||
|
|
// 2:<hash>:second line
|
||
|
|
// 3:<hash>:third needle
|
||
|
|
// 4:<hash>:fourth line
|
||
|
|
// --- Match around line 5 ---
|
||
|
|
// 4:<hash>:fourth line
|
||
|
|
// 5:<hash>:fifth needle
|
||
|
|
|
||
|
|
lines := strings.Split(got, "\n")
|
||
|
|
|
||
|
|
findLine := func(prefix string) bool {
|
||
|
|
for _, l := range lines {
|
||
|
|
if strings.HasPrefix(l, prefix) {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check anchors
|
||
|
|
if !findLine("--- Match around line 3 ---") {
|
||
|
|
t.Errorf("missing match anchor for line 3")
|
||
|
|
}
|
||
|
|
if !findLine("--- Match around line 5 ---") {
|
||
|
|
t.Errorf("missing match anchor for line 5")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check specific hashline prefixes
|
||
|
|
h2 := hashLine("second line")
|
||
|
|
h3 := hashLine("third needle")
|
||
|
|
h5 := hashLine("fifth needle")
|
||
|
|
|
||
|
|
if !findLine("2:" + h2 + ":second line") {
|
||
|
|
t.Errorf("missing correctly hashed context line 2")
|
||
|
|
}
|
||
|
|
if !findLine("3:" + h3 + ":third needle") {
|
||
|
|
t.Errorf("missing correctly hashed match line 3")
|
||
|
|
}
|
||
|
|
if !findLine("5:" + h5 + ":fifth needle") {
|
||
|
|
t.Errorf("missing correctly hashed match line 5")
|
||
|
|
}
|
||
|
|
}
|