Files
zzet--gortex/internal/analysis/communities_label_test.go
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

237 lines
6.8 KiB
Go

package analysis
import "testing"
func TestPureClusterLabel(t *testing.T) {
tests := []struct {
name string
files []string
want string
}{
{
name: "all files under one deep dir",
files: []string{
"gortex/internal/parser/languages/cpp.go",
"gortex/internal/parser/languages/dart.go",
"gortex/internal/parser/languages/python.go",
},
want: "parser/languages",
},
{
name: "all files under repo + plumbing only",
files: []string{
"gortex/internal/parser/extractor.go",
"gortex/internal/graph/edge.go",
},
want: "",
},
{
name: "single file → plumbing stripped from directory",
files: []string{
"gortex/internal/server/dashboard.go",
},
want: "server",
},
{
name: "empty",
files: []string{},
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := pureClusterLabel(tt.files)
if got != tt.want {
t.Errorf("pureClusterLabel(%v) = %q; want %q", tt.files, got, tt.want)
}
})
}
}
func TestMixedClusterLabel(t *testing.T) {
tests := []struct {
name string
files []string
want string
}{
{
name: "spread across many top-level dirs surfaces spread",
files: []string{
"gortex/internal/parser/languages/abap.go",
"gortex/internal/parser/languages/actionscript.go",
"gortex/internal/parser/languages/ada.go",
"gortex/internal/parser/extractor.go",
"gortex/internal/dataflow/dataflow.go",
"gortex/internal/graph/edge.go",
"gortex/internal/graph/node.go",
"gortex/internal/mcp/tools_ast.go",
"gortex/internal/llm/daemon_backend.go",
},
want: "parser/languages +5 dirs",
},
{
name: "two dirs, modal wins with +1 dirs",
files: []string{
"gortex/internal/foo/a.go",
"gortex/internal/foo/b.go",
"gortex/internal/bar/x.go",
},
want: "foo +1 dirs",
},
{
name: "single dir → no spread annotation",
files: []string{
"gortex/internal/foo/a.go",
"gortex/internal/foo/b.go",
},
want: "foo",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := mixedClusterLabel(tt.files)
if got != tt.want {
t.Errorf("mixedClusterLabel = %q; want %q", got, tt.want)
}
})
}
}
func TestDisambiguateLabelsCascadesToSizeSuffix(t *testing.T) {
// Two clusters share modal dir AND first-file AND second-file —
// only the size suffix breaks the tie.
communities := []Community{
{ID: "a", Label: "server", Size: 50, Files: []string{"server/h.go", "server/m.go"}},
{ID: "b", Label: "server", Size: 70, Files: []string{"server/h.go", "server/m.go"}},
}
disambiguateLabels(communities)
if communities[0].Label == communities[1].Label {
t.Fatalf("size tiebreaker failed: both %q", communities[0].Label)
}
}
func TestDisambiguateLabelsOrdinalTiebreaker(t *testing.T) {
// Three clusters with the same dir, same first two files, AND
// the same size — only the ordinal tiebreaker can split them.
communities := []Community{
{ID: "a", Label: "mcp", Size: 15, Files: []string{"mcp/memories.go", "mcp/notes.go"}},
{ID: "b", Label: "mcp", Size: 15, Files: []string{"mcp/memories.go", "mcp/notes.go"}},
{ID: "c", Label: "mcp", Size: 15, Files: []string{"mcp/memories.go", "mcp/notes.go"}},
}
disambiguateLabels(communities)
labels := map[string]bool{}
for _, c := range communities {
if labels[c.Label] {
t.Fatalf("ordinal tiebreaker failed: duplicate %q", c.Label)
}
labels[c.Label] = true
}
}
func TestDisambiguateLabelsUsesHubFirst(t *testing.T) {
// Two pure clusters under the same directory should get their
// hub-symbol names appended — the most meaningful disambiguator.
// File basenames are only the fallback when the hub is missing.
communities := []Community{
{
ID: "community-1",
Label: "parser/languages",
Hub: "GoExtractor",
Files: []string{
"gortex/internal/parser/languages/cpp.go",
"gortex/internal/parser/languages/csharp.go",
},
},
{
ID: "community-2",
Label: "parser/languages",
Hub: "DartExtractor",
Files: []string{
"gortex/internal/parser/languages/dart.go",
"gortex/internal/parser/languages/flutter.go",
},
},
{
ID: "community-3",
Label: "server",
Hub: "RunServer",
Files: []string{"gortex/internal/server/handler.go"},
},
}
disambiguateLabels(communities)
wantA := "parser/languages · GoExtractor"
wantB := "parser/languages · DartExtractor"
if communities[0].Label != wantA {
t.Errorf("community[0] = %q; want %q", communities[0].Label, wantA)
}
if communities[1].Label != wantB {
t.Errorf("community[1] = %q; want %q", communities[1].Label, wantB)
}
if communities[2].Label != "server" {
t.Errorf("unique label was modified: %q", communities[2].Label)
}
}
func TestDisambiguateFallsBackToFileWhenNoHub(t *testing.T) {
// When the hub is missing (e.g. legacy data, no member with a
// resolvable name), the cascade falls back to file basenames.
communities := []Community{
{
ID: "a", Label: "parser/languages", Hub: "",
Files: []string{"gortex/internal/parser/languages/cpp.go"},
},
{
ID: "b", Label: "parser/languages", Hub: "",
Files: []string{"gortex/internal/parser/languages/dart.go"},
},
}
disambiguateLabels(communities)
if communities[0].Label == communities[1].Label {
t.Fatalf("fallback failed: both %q", communities[0].Label)
}
}
func TestCleanHubName(t *testing.T) {
cases := map[string]string{
"": "",
"runServer": "runServer",
"(*Extractor).Extract": "Extractor.Extract",
"(Receiver).Method": "Receiver.Method",
"WayTooLongFunctionNameOfAReallyLongType.WithAMethod": "WayTooLongFunctionNameOfAReally…",
}
for in, want := range cases {
got := cleanHubName(in)
if got != want {
t.Errorf("cleanHubName(%q) = %q; want %q", in, got, want)
}
}
}
func TestInferCommunityLabelDistinguishesSameBasename(t *testing.T) {
// Two clusters whose basenames collide ("languages") but whose
// contents differ should produce different labels.
pureFiles := []string{
"gortex/internal/parser/languages/cpp.go",
"gortex/internal/parser/languages/dart.go",
"gortex/internal/parser/languages/python.go",
}
mixedFiles := []string{
"gortex/internal/parser/languages/abap.go",
"gortex/internal/parser/extractor.go",
"gortex/internal/dataflow/dataflow.go",
"gortex/internal/graph/edge.go",
"gortex/internal/mcp/tools_ast.go",
}
pure := inferCommunityLabel(nil, nil, pureFiles)
mixed := inferCommunityLabel(nil, nil, mixedFiles)
if pure == mixed {
t.Fatalf("two structurally distinct clusters share label %q (regression — naming collision is back)", pure)
}
if pure != "parser/languages" {
t.Errorf("pure cluster label = %q; want %q", pure, "parser/languages")
}
if mixed == "languages" || mixed == "parser/languages" {
t.Errorf("mixed cluster label = %q; should surface its spread", mixed)
}
}