This commit is contained in:
2026-06-22 08:55:57 +08:00
parent dbb87823e8
commit 6ade6e8fa9
325 changed files with 41131 additions and 855 deletions
+125
View File
@@ -0,0 +1,125 @@
package handlers_test
import (
"context"
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/yan1h/agent-coding-workflow/internal/acp/handlers"
)
func TestGrep_HappyPath(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(tmp, "a.go"), []byte("package a\n\nfunc Foo() {}\n"), 0o644))
require.NoError(t, os.WriteFile(filepath.Join(tmp, "b.go"), []byte("package b\n\nfunc Bar() {}\n"), 0o644))
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "func Foo"}))
require.Nil(t, res.Err)
var out struct {
Matches []struct {
File string `json:"file"`
Line int `json:"line"`
Text string `json:"text"`
} `json:"matches"`
Truncated bool `json:"truncated"`
}
require.NoError(t, json.Unmarshal(res.OK, &out))
require.Len(t, out.Matches, 1)
assert.Equal(t, "a.go", out.Matches[0].File)
assert.Equal(t, 3, out.Matches[0].Line)
assert.Contains(t, out.Matches[0].Text, "func Foo")
}
func TestGrep_CaseInsensitiveByDefault(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(tmp, "a.go"), []byte("HELLO world\n"), 0o644))
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "hello"}))
require.Nil(t, res.Err)
var out struct {
Matches []any `json:"matches"`
}
require.NoError(t, json.Unmarshal(res.OK, &out))
require.Len(t, out.Matches, 1)
}
func TestGrep_PathOutsideWorktree(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
outside := filepath.Join(filepath.VolumeName(tmp)+string(filepath.Separator), "etc")
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "x", "path": outside}))
require.NotNil(t, res.Err)
assert.Equal(t, -32001, res.Err.Code)
}
func TestGrep_InvalidPattern(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "[invalid("}))
require.NotNil(t, res.Err)
assert.Equal(t, -32602, res.Err.Code)
}
func TestGrep_EmptyPattern(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": ""}))
require.NotNil(t, res.Err)
assert.Equal(t, -32602, res.Err.Code)
}
func TestGrep_MaxMatchesCap(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
// 10 matching lines; cap at 3.
content := "m\nm\nm\nm\nm\nm\nm\nm\nm\nm\n"
require.NoError(t, os.WriteFile(filepath.Join(tmp, "a.txt"), []byte(content), 0o644))
h := &handlers.GrepHandler{MaxMatches: 3, MaxFiles: 100, MaxFileSize: 1 << 20}
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "m"}))
require.Nil(t, res.Err)
var out struct {
Matches []any `json:"matches"`
Truncated bool `json:"truncated"`
}
require.NoError(t, json.Unmarshal(res.OK, &out))
require.Len(t, out.Matches, 3)
require.True(t, out.Truncated)
}
func TestGrep_SkipsGitDir(t *testing.T) {
t.Parallel()
tmp := t.TempDir()
require.NoError(t, os.MkdirAll(filepath.Join(tmp, ".git"), 0o755))
require.NoError(t, os.WriteFile(filepath.Join(tmp, ".git", "config"), []byte("secret pattern\n"), 0o644))
require.NoError(t, os.WriteFile(filepath.Join(tmp, "a.txt"), []byte("normal pattern\n"), 0o644))
h := handlers.NewGrepHandler()
sess := handlers.SessionContext{CwdPath: tmp}
res := h.Handle(context.Background(), sess, mustJSON(t, map[string]any{"sessionId": "x", "pattern": "pattern"}))
require.Nil(t, res.Err)
var out struct {
Matches []struct {
File string `json:"file"`
} `json:"matches"`
}
require.NoError(t, json.Unmarshal(res.OK, &out))
require.Len(t, out.Matches, 1)
assert.Equal(t, "a.txt", out.Matches[0].File)
}