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,107 @@
|
||||
package analysis
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/zzet/gortex/internal/graph"
|
||||
)
|
||||
|
||||
// seedComponentTestGraph builds a hub-and-spoke graph: two SCC
|
||||
// triangles + one hub every node points at. Gives predictable
|
||||
// WCC + SCC answers.
|
||||
func seedComponentTestGraph() *graph.Graph {
|
||||
g := graph.New()
|
||||
for _, id := range []string{"a", "b", "c", "d", "e", "f", "hub"} {
|
||||
g.AddNode(&graph.Node{ID: id, Kind: graph.KindFunction, Name: id, FilePath: id + ".go"})
|
||||
}
|
||||
edges := [][2]string{
|
||||
{"a", "b"}, {"b", "c"}, {"c", "a"}, // triangle 1
|
||||
{"d", "e"}, {"e", "f"}, {"f", "d"}, // triangle 2
|
||||
{"c", "d"}, // bridge
|
||||
{"a", "hub"}, {"b", "hub"}, {"c", "hub"},
|
||||
{"d", "hub"}, {"e", "hub"}, {"f", "hub"},
|
||||
}
|
||||
for _, e := range edges {
|
||||
g.AddEdge(&graph.Edge{From: e[0], To: e[1], Kind: graph.EdgeCalls, FilePath: "x.go"})
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func TestComputeWCC_OneComponent(t *testing.T) {
|
||||
g := seedComponentTestGraph()
|
||||
res := ComputeWCC(g, ComponentOptions{})
|
||||
require.Len(t, res, 1, "all 7 nodes form one WCC; got %v", res)
|
||||
assert.Equal(t, 7, res[0].Size)
|
||||
}
|
||||
|
||||
func TestComputeWCC_HonoursEdgeFilter(t *testing.T) {
|
||||
g := seedComponentTestGraph()
|
||||
// Filter out the call edges entirely → no surviving edges → every node
|
||||
// becomes its own singleton component.
|
||||
res := ComputeWCC(g, ComponentOptions{
|
||||
EdgeKinds: []graph.EdgeKind{graph.EdgeReferences},
|
||||
})
|
||||
assert.Len(t, res, 7,
|
||||
"with no surviving edges every node should be a singleton; got %v", res)
|
||||
}
|
||||
|
||||
func TestComputeSCC_ThreeComponents(t *testing.T) {
|
||||
g := seedComponentTestGraph()
|
||||
res := ComputeSCC(g, ComponentOptions{})
|
||||
// 7 SCCs: {a,b,c}, {d,e,f}, {hub} (singleton). But the hub is
|
||||
// trivial — without MinSize, expect 3 with sizes [3, 3, 1].
|
||||
require.GreaterOrEqual(t, len(res), 3)
|
||||
|
||||
bySize := map[int]int{}
|
||||
for _, r := range res {
|
||||
bySize[r.Size]++
|
||||
}
|
||||
assert.Equal(t, 2, bySize[3], "should find two 3-node SCCs (the triangles); got %v", res)
|
||||
}
|
||||
|
||||
func TestComputeSCC_MinSize_DropsSingletons(t *testing.T) {
|
||||
g := seedComponentTestGraph()
|
||||
res := ComputeSCC(g, ComponentOptions{MinSize: 2})
|
||||
for _, r := range res {
|
||||
assert.GreaterOrEqual(t, r.Size, 2,
|
||||
"MinSize=2 should drop singleton SCCs; got %v", r)
|
||||
}
|
||||
}
|
||||
|
||||
// TestComputeSCC_Iterative_NoStackOverflow constructs a deep
|
||||
// straight-line graph (1 -> 2 -> 3 -> ... -> N) to make sure the
|
||||
// iterative Tarjan stays in heap and doesn't blow the goroutine
|
||||
// call stack. N = 10k; recursive Tarjan would fall over.
|
||||
func TestComputeSCC_Iterative_NoStackOverflow(t *testing.T) {
|
||||
const n = 10000
|
||||
g := graph.New()
|
||||
for i := 0; i < n; i++ {
|
||||
id := charID(i)
|
||||
g.AddNode(&graph.Node{ID: id, Kind: graph.KindFunction, Name: id, FilePath: "x.go"})
|
||||
}
|
||||
for i := 0; i < n-1; i++ {
|
||||
g.AddEdge(&graph.Edge{
|
||||
From: charID(i), To: charID(i + 1), Kind: graph.EdgeCalls, FilePath: "x.go",
|
||||
})
|
||||
}
|
||||
res := ComputeSCC(g, ComponentOptions{})
|
||||
// A DAG of N nodes has N singleton SCCs.
|
||||
assert.Equal(t, n, len(res))
|
||||
}
|
||||
|
||||
func charID(i int) string {
|
||||
// fmt.Sprintf is fine but we want zero allocs in the loop body — just
|
||||
// build a deterministic string ID.
|
||||
const hex = "0123456789abcdef"
|
||||
out := make([]byte, 0, 8)
|
||||
for x := i; ; x /= 16 {
|
||||
out = append([]byte{hex[x%16]}, out...)
|
||||
if x < 16 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return "n_" + string(out)
|
||||
}
|
||||
Reference in New Issue
Block a user