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
61 lines
2.2 KiB
Go
61 lines
2.2 KiB
Go
package mcp
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
"github.com/zzet/gortex/internal/query"
|
|
)
|
|
|
|
func dispatchGraph(t *testing.T) *graph.Graph {
|
|
t.Helper()
|
|
g := graph.New()
|
|
g.AddNode(&graph.Node{ID: "pkg.go::I", Kind: graph.KindInterface, Name: "I"})
|
|
g.AddNode(&graph.Node{ID: "pkg.go::A", Kind: graph.KindType, Name: "A"})
|
|
g.AddNode(&graph.Node{ID: "pkg.go::B", Kind: graph.KindType, Name: "B"})
|
|
g.AddEdge(&graph.Edge{From: "pkg.go::A", To: "pkg.go::I", Kind: graph.EdgeImplements})
|
|
g.AddEdge(&graph.Edge{From: "pkg.go::B", To: "pkg.go::I", Kind: graph.EdgeImplements})
|
|
return g
|
|
}
|
|
|
|
func TestDispatchImplementorCount(t *testing.T) {
|
|
s := &Server{graph: dispatchGraph(t)}
|
|
require.Equal(t, 2, s.dispatchImplementorCount("pkg.go::I"))
|
|
require.Equal(t, 0, s.dispatchImplementorCount("pkg.go::A"))
|
|
require.Equal(t, 0, s.dispatchImplementorCount("pkg.go::missing"))
|
|
}
|
|
|
|
func TestAttachRelatedToolsCue_DispatchHeavy(t *testing.T) {
|
|
s := &Server{graph: dispatchGraph(t), session: &sessionState{}}
|
|
|
|
// A dispatch-heavy target gets the find_implementations cue.
|
|
sg := &query.SubGraph{}
|
|
s.attachRelatedToolsCue(context.Background(), sg, "pkg.go::I")
|
|
require.Contains(t, sg.RelatedTools, "find_implementations")
|
|
|
|
// Once per session: a second dispatch-heavy result does NOT repeat it.
|
|
sg2 := &query.SubGraph{}
|
|
s.attachRelatedToolsCue(context.Background(), sg2, "pkg.go::I")
|
|
require.Empty(t, sg2.RelatedTools, "the cue is emitted at most once per session")
|
|
}
|
|
|
|
func TestAttachRelatedToolsCue_NotDispatchHeavy(t *testing.T) {
|
|
s := &Server{graph: dispatchGraph(t), session: &sessionState{}}
|
|
// A plain symbol with no implementors gets no cue.
|
|
sg := &query.SubGraph{}
|
|
s.attachRelatedToolsCue(context.Background(), sg, "pkg.go::A")
|
|
require.Empty(t, sg.RelatedTools)
|
|
}
|
|
|
|
func TestAttachRelatedToolsCue_YieldsToEmptinessCaveats(t *testing.T) {
|
|
s := &Server{graph: dispatchGraph(t), session: &sessionState{}}
|
|
// A zero-edge / tier-filtered result owns the "why empty" story — the
|
|
// discovery cue must not compete with it.
|
|
sg := &query.SubGraph{Caveat: &graph.ZeroEdgeCaveat{}}
|
|
s.attachRelatedToolsCue(context.Background(), sg, "pkg.go::I")
|
|
require.Empty(t, sg.RelatedTools)
|
|
}
|