Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

192 lines
5.8 KiB
Go

package hooks
import (
"strings"
"testing"
)
// newIndexedBridge stubs the daemon file-indexed probe so every queried
// file looks indexed with the given symbol count, for the duration of the
// test. Used to exercise enrichBash's ReadSource path without a real daemon.
// Returns a dummy port (0) so the legacy `port := newIndexedBridge(...)`
// call sites still compile; the value is unused now that the indexed check
// routes through the stubbed fileIndexedFn seam rather than an HTTP port.
func newIndexedBridge(t *testing.T, symbols int) int {
t.Helper()
prev := fileIndexedFn
t.Cleanup(func() { fileIndexedFn = prev })
fileIndexedFn = func(_, _ string) (bool, int) { return symbols > 0, symbols }
return 0
}
func TestEnrichBash_GrepHit_Denies(t *testing.T) {
redirectTelemetry(t)
stubProbe(t, []grepSymbolHit{
{Name: "handleFoo", Kind: "function", FilePath: "internal/a.go", Line: 42},
}, nil)
r := enrichBash(map[string]any{"command": `grep -rn "handleFoo" .`}, "")
if !r.deny {
t.Fatalf("expected deny on grep hit, got %+v", r)
}
if !strings.Contains(r.reason, "handleFoo") {
t.Error("deny reason should mention the pattern")
}
if !strings.Contains(r.reason, "internal/a.go:42") {
t.Error("deny reason should list the hit")
}
}
func TestEnrichBash_GrepMiss_SoftGuidance(t *testing.T) {
redirectTelemetry(t)
stubProbe(t, nil, nil) // daemon reachable, no hits
r := enrichBash(map[string]any{"command": `grep -rn "handleFoo" .`}, "")
if r.deny {
t.Fatal("miss should not deny")
}
if !strings.Contains(r.context, "search_symbols") {
t.Error("miss should return soft guidance mentioning search_symbols")
}
}
func TestEnrichBash_GrepPiped_PassesThrough(t *testing.T) {
// grep after | is a filter on upstream output — not a codebase search.
rec := stubProbe(t, nil, nil)
r := enrichBash(map[string]any{"command": `go test ./... | grep FAIL`}, "")
if r.deny || r.context != "" {
t.Errorf("piped grep should pass through, got %+v", r)
}
if len(rec.calls) != 0 {
t.Errorf("piped grep should not probe daemon, got calls %v", rec.calls)
}
}
func TestEnrichBash_RgBare_Denies(t *testing.T) {
redirectTelemetry(t)
stubProbe(t, []grepSymbolHit{
{Name: "MyType", Kind: "type", FilePath: "a.go", Line: 5},
}, nil)
r := enrichBash(map[string]any{"command": `rg MyType`}, "")
if !r.deny {
t.Fatalf("expected deny, got %+v", r)
}
}
func TestEnrichBash_FindName_Denies(t *testing.T) {
redirectTelemetry(t)
stubProbe(t, []grepSymbolHit{
{Name: "Handler", Kind: "type", FilePath: "x.go", Line: 10},
}, nil)
r := enrichBash(map[string]any{"command": `find . -name "Handler*"`}, "")
if !r.deny {
t.Fatalf("expected deny for find -name with symbol-shaped root, got %+v", r)
}
}
func TestEnrichBash_FindNameGoFiles_NoProbe(t *testing.T) {
// `-name "*.go"` reduces to ".go" which is not symbol-shaped — no probe,
// no deny. Returns soft guidance because the pattern is >2 chars.
rec := stubProbe(t, nil, nil)
r := enrichBash(map[string]any{"command": `find . -name "*.go"`}, "")
if r.deny {
t.Fatal("find -name *.go should not deny")
}
if len(rec.calls) != 0 {
t.Errorf("non-symbol-shaped name should not probe, got %v", rec.calls)
}
}
func TestEnrichBash_FindTypeD_Passthrough(t *testing.T) {
rec := stubProbe(t, nil, nil)
r := enrichBash(map[string]any{"command": `find . -maxdepth 3 -type d`}, "")
if r.deny || r.context != "" {
t.Errorf("find -type d should pass through, got %+v", r)
}
if len(rec.calls) != 0 {
t.Error("find without -name should not probe")
}
}
func TestEnrichBash_CatIndexedSource_Denies(t *testing.T) {
newIndexedBridge(t, 17)
r := enrichBash(map[string]any{"command": `cat /repo/handler.go`}, "")
if !r.deny {
t.Fatalf("expected deny for cat of indexed source, got %+v", r)
}
if !strings.Contains(r.reason, "/repo/handler.go") {
t.Error("deny reason should mention the file path")
}
if !strings.Contains(r.reason, "17 symbols") {
t.Error("deny reason should include the symbol count")
}
if !strings.Contains(r.reason, "get_file_summary") {
t.Error("deny reason should point to get_file_summary")
}
}
func TestEnrichBash_CatUnindexedSource_SoftGuidance(t *testing.T) {
// probe not stubbed → file treated as not indexed.
r := enrichBash(map[string]any{"command": `head -20 /tmp/foo.go`}, "")
if r.deny {
t.Fatal("unindexed source should not deny")
}
if !strings.Contains(r.context, "get_symbol_source") {
t.Error("soft guidance should mention get_symbol_source")
}
}
func TestEnrichBash_CatLogfile_Passthrough(t *testing.T) {
r := enrichBash(map[string]any{"command": `cat /tmp/app.log`}, "")
if r.deny || r.context != "" {
t.Errorf("cat of non-source file should pass through, got %+v", r)
}
}
func TestEnrichBash_EmptyCommand(t *testing.T) {
r := enrichBash(map[string]any{"command": ""}, "")
if r.deny || r.context != "" {
t.Errorf("empty command should pass through, got %+v", r)
}
}
func TestEnrichBash_UnrelatedCommand(t *testing.T) {
rec := stubProbe(t, nil, nil)
for _, cmd := range []string{
`ls /repo`,
`go build ./...`,
`git status`,
`echo hello`,
} {
r := enrichBash(map[string]any{"command": cmd}, "")
if r.deny || r.context != "" {
t.Errorf("%q should pass through, got %+v", cmd, r)
}
}
if len(rec.calls) != 0 {
t.Errorf("unrelated commands should not probe, got %v", rec.calls)
}
}
func TestEnrichBash_TelemetryTaggedAsBash(t *testing.T) {
logPath := redirectTelemetry(t)
stubProbe(t, []grepSymbolHit{
{Name: "handleFoo", Kind: "function", FilePath: "a.go", Line: 1},
}, nil)
_ = enrichBash(map[string]any{"command": `grep -rn handleFoo .`}, "")
recs := readDecisions(t, logPath)
if len(recs) != 1 {
t.Fatalf("expected 1 telemetry record, got %d", len(recs))
}
if recs[0].Tool != "Bash" {
t.Errorf("tool = %q, want %q", recs[0].Tool, "Bash")
}
if recs[0].Decision != DecisionProbedHit {
t.Errorf("decision = %v, want probed_hit", recs[0].Decision)
}
}