chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package analysis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/zzet/gortex/internal/graph"
|
||||
)
|
||||
|
||||
// buildEdgeGraph constructs a small in-memory graph from (from,to) call
|
||||
// edges. Node IDs follow the "<pkg>/file.go::Sym" shape so packageOfID
|
||||
// resolves a meaningful package directory.
|
||||
func buildEdgeGraph(t *testing.T, edges [][2]string) graph.Store {
|
||||
t.Helper()
|
||||
g := graph.New()
|
||||
seen := map[string]bool{}
|
||||
add := func(id string) {
|
||||
if seen[id] {
|
||||
return
|
||||
}
|
||||
seen[id] = true
|
||||
path := id
|
||||
if i := indexOfSep(id); i >= 0 {
|
||||
path = id[:i]
|
||||
}
|
||||
g.AddNode(&graph.Node{ID: id, Kind: graph.KindFunction, Name: id, FilePath: path})
|
||||
}
|
||||
for _, e := range edges {
|
||||
add(e[0])
|
||||
add(e[1])
|
||||
}
|
||||
for _, e := range edges {
|
||||
g.AddEdge(&graph.Edge{From: e[0], To: e[1], Kind: graph.EdgeCalls})
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func indexOfSep(s string) int {
|
||||
for i := 0; i+1 < len(s); i++ {
|
||||
if s[i] == ':' && s[i+1] == ':' {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func TestWalkCacheKeyDeterministic(t *testing.T) {
|
||||
g := buildEdgeGraph(t, [][2]string{
|
||||
{"pkg/a.go::A", "pkg/b.go::B"},
|
||||
{"pkg/b.go::B", "pkg/c.go::C"},
|
||||
})
|
||||
s1 := BuildAdjacencySnapshot(g)
|
||||
s2 := BuildAdjacencySnapshot(g)
|
||||
k1 := s1.WalkCacheKey([]string{"pkg/a.go::A"}, 0)
|
||||
k2 := s2.WalkCacheKey([]string{"pkg/a.go::A"}, 0)
|
||||
if k1 == "" {
|
||||
t.Fatal("expected non-empty key")
|
||||
}
|
||||
if k1 != k2 {
|
||||
t.Fatalf("key not deterministic across identical snapshots: %q vs %q", k1, k2)
|
||||
}
|
||||
// Seed order must not matter (sorted internally).
|
||||
if got := s1.WalkCacheKey([]string{"pkg/a.go::A", "pkg/b.go::B"}, 0); got == k1 {
|
||||
t.Fatal("different seed set should produce a different key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWalkCacheKeyPackageInvalidation(t *testing.T) {
|
||||
base := [][2]string{
|
||||
{"pkg/a.go::A", "pkg/b.go::B"},
|
||||
{"other/x.go::X", "other/y.go::Y"},
|
||||
}
|
||||
g1 := buildEdgeGraph(t, base)
|
||||
s1 := BuildAdjacencySnapshot(g1)
|
||||
seeds := []string{"other/x.go::X"}
|
||||
k1 := s1.WalkCacheKey(seeds, 0)
|
||||
|
||||
// Change a package UNRELATED to the seed's dependency set (pkg/*).
|
||||
// The seed walk (other/*) must keep the same key — the incremental
|
||||
// property: an edit to pkg/ doesn't bust an other/ walk.
|
||||
g2 := buildEdgeGraph(t, append([][2]string{
|
||||
{"pkg/a.go::A", "pkg/b.go::B2new"},
|
||||
}, base...))
|
||||
s2 := BuildAdjacencySnapshot(g2)
|
||||
k2 := s2.WalkCacheKey(seeds, 0)
|
||||
if k1 != k2 {
|
||||
t.Fatalf("unrelated-package edit must not change the walk key: %q vs %q", k1, k2)
|
||||
}
|
||||
|
||||
// Now change the seed's OWN package: the key must change (miss).
|
||||
g3 := buildEdgeGraph(t, [][2]string{
|
||||
{"pkg/a.go::A", "pkg/b.go::B"},
|
||||
{"other/x.go::X", "other/y.go::Ynew"}, // seed's out-edge target changed
|
||||
})
|
||||
s3 := BuildAdjacencySnapshot(g3)
|
||||
k3 := s3.WalkCacheKey(seeds, 0)
|
||||
if k1 == k3 {
|
||||
t.Fatal("changing the seed's dependency package must change the walk key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageRootsPopulated(t *testing.T) {
|
||||
g := buildEdgeGraph(t, [][2]string{
|
||||
{"pkg/a.go::A", "pkg/b.go::B"},
|
||||
{"other/x.go::X", "other/y.go::Y"},
|
||||
})
|
||||
s := BuildAdjacencySnapshot(g)
|
||||
if s.PackageRootCount() < 2 {
|
||||
t.Fatalf("expected >=2 package roots, got %d", s.PackageRootCount())
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageOfID(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"gortex/internal/mcp/server.go::NewServer": "gortex/internal/mcp",
|
||||
"pkg/a.go::A": "pkg",
|
||||
"top.go::Sym": "",
|
||||
"a/b/c/f.go::S": "a/b/c",
|
||||
}
|
||||
for id, want := range cases {
|
||||
if got := packageOfID(id); got != want {
|
||||
t.Errorf("packageOfID(%q) = %q, want %q", id, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user