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

107 lines
3.5 KiB
Go

package mcp
import (
"strings"
"testing"
"github.com/zzet/gortex/internal/graph"
)
func TestExploreLocalizableKind(t *testing.T) {
// Real edit targets are localizable; structural noise is not.
localizable := []graph.NodeKind{
graph.KindFunction, graph.KindMethod, graph.KindType,
graph.KindInterface, graph.KindField, graph.KindConstant,
graph.KindVariable,
}
for _, k := range localizable {
if !exploreLocalizableKind(k) {
t.Errorf("kind %q should be localizable", k)
}
}
noise := []graph.NodeKind{
graph.KindParam, graph.KindLocal, graph.KindClosure,
graph.KindGenericParam, graph.KindImport, graph.KindFile,
}
for _, k := range noise {
if exploreLocalizableKind(k) {
t.Errorf("kind %q should be filtered out", k)
}
}
}
func exploreTestTargets() []exploreTarget {
fn := &graph.Node{Name: "DoWithRetry", Kind: graph.KindFunction,
FilePath: "retry.go", StartLine: 11, EndLine: 20, Language: "go"}
helper := &graph.Node{Name: "Backoff", Kind: graph.KindFunction,
FilePath: "retry.go", StartLine: 6, EndLine: 8, Language: "go"}
caller := &graph.Node{Name: "Fetch", Kind: graph.KindFunction,
FilePath: "client.go", StartLine: 4, EndLine: 6, Language: "go"}
return []exploreTarget{
{node: fn, score: 0.9, callers: []*graph.Node{caller}, callees: []*graph.Node{helper},
source: "func DoWithRetry(max int) error {\n\treturn nil\n}"},
{node: helper, score: 0.5, callers: []*graph.Node{fn},
source: "func Backoff(n int) int {\n\treturn n\n}"},
}
}
func TestRenderExploreShape(t *testing.T) {
out := (&Server{}).renderExplore("the retry backoff never fires on 429", exploreTestTargets(), 9000)
// Ranked targets, with citeable path:line locations.
for _, want := range []string{
"EXPLORE — the retry backoff never fires on 429",
"## Likely targets",
"1. DoWithRetry function · retry.go:11-20",
"2. Backoff function · retry.go:6-8",
"^ callers: Fetch (client.go:4-6)",
"v calls: Backoff (retry.go:6-8)",
"func DoWithRetry(max int) error", // full body for hot target
"## Files to change",
"- retry.go · Backoff, DoWithRetry",
"— Completeness: 2 candidate symbol(s) across 1 file(s)",
"FILES / SYMBOLS / EVIDENCE",
} {
if !strings.Contains(out, want) {
t.Errorf("render missing %q\n--- got ---\n%s", want, out)
}
}
}
func TestRenderExploreBudgetTruncation(t *testing.T) {
// A budget below the body cost forces demotion to signatures, but every
// candidate's LOCATION must still be listed (file-hit/symbol-hit never
// depend on the budget) and the truncation must be reported honestly.
out := (&Server{}).renderExplore("task", exploreTestTargets(), exploreMinBudgetTokens)
for _, want := range []string{
"1. DoWithRetry function · retry.go:11-20",
"2. Backoff function · retry.go:6-8",
"— Completeness:",
} {
if !strings.Contains(out, want) {
t.Errorf("truncated render missing %q", want)
}
}
}
func TestExploreHelpers(t *testing.T) {
if got := clampInt(5, 1, 3); got != 3 {
t.Errorf("clampInt hi: got %d", got)
}
if got := clampInt(0, 2, 10); got != 2 {
t.Errorf("clampInt lo: got %d", got)
}
if got := truncateOneLine("a\n b\tc", 100); got != "a b c" {
t.Errorf("truncateOneLine collapse: %q", got)
}
if got := truncateOneLine(strings.Repeat("x", 10), 4); got != "xxxx…" {
t.Errorf("truncateOneLine cap: %q", got)
}
if got := firstLines("1\n2\n3\n4", 2); got != "1\n2" {
t.Errorf("firstLines: %q", got)
}
if got := dedupStrings([]string{"b", "a", "b"}); strings.Join(got, ",") != "a,b" {
t.Errorf("dedupStrings: %v", got)
}
}