You've already forked agentic-coding-workflow
126 lines
4.2 KiB
Go
126 lines
4.2 KiB
Go
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)
|
|
}
|