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

139 lines
5.0 KiB
Go

package indexer
import (
"reflect"
"testing"
"github.com/zzet/gortex/internal/semantic"
)
// TestOrderIndexersBySpecGroup_GroupsBySpecDeterministically asserts the
// deferred-enrich dispatch order groups repos by their language set (so
// repos needing the same LSP servers run contiguously and the router's
// capped pool churns through fewer distinct provider keys), breaking ties
// by repo prefix — and that the order is stable / independent of input
// order.
func TestOrderIndexersBySpecGroup_GroupsBySpecDeterministically(t *testing.T) {
goA := &Indexer{repoPrefix: "alpha"}
goB := &Indexer{repoPrefix: "bravo"}
rust := &Indexer{repoPrefix: "charlie"}
tsA := &Indexer{repoPrefix: "delta"}
tsB := &Indexer{repoPrefix: "echo"}
langSets := map[*Indexer][]string{
goA: {"go"},
goB: {"go"},
rust: {"rust"},
tsA: {"javascript", "typescript"},
tsB: {"javascript", "typescript"},
}
// Two different input orders must yield the same output.
in1 := []*Indexer{tsB, goB, rust, goA, tsA}
in2 := []*Indexer{rust, tsA, goA, tsB, goB}
// Expected: grouped by joined-language key ("go" < "javascript,typescript"
// < "rust"), then by repoPrefix within a group.
want := []*Indexer{goA, goB, tsA, tsB, rust}
got1 := orderIndexersBySpecGroup(in1, langSets)
got2 := orderIndexersBySpecGroup(in2, langSets)
if !reflect.DeepEqual(got1, want) {
t.Fatalf("order mismatch for in1:\n got %s\nwant %s", prefixes(got1), prefixes(want))
}
if !reflect.DeepEqual(got2, want) {
t.Fatalf("order not deterministic across input orders:\n in2 got %s\nwant %s", prefixes(got2), prefixes(want))
}
// Same-spec repos must be contiguous: alpha,bravo (go) then delta,echo (ts).
if got1[0].repoPrefix != "alpha" || got1[1].repoPrefix != "bravo" {
t.Fatalf("go repos not contiguous+ordered: %s", prefixes(got1))
}
if got1[2].repoPrefix != "delta" || got1[3].repoPrefix != "echo" {
t.Fatalf("ts repos not contiguous+ordered: %s", prefixes(got1))
}
}
// TestOrderIndexersBySpecGroup_DoesNotMutateInput confirms the helper
// returns a fresh slice and leaves the caller's slice untouched.
func TestOrderIndexersBySpecGroup_DoesNotMutateInput(t *testing.T) {
a := &Indexer{repoPrefix: "z"}
b := &Indexer{repoPrefix: "a"}
in := []*Indexer{a, b}
langSets := map[*Indexer][]string{a: {"go"}, b: {"go"}}
_ = orderIndexersBySpecGroup(in, langSets)
if in[0] != a || in[1] != b {
t.Fatalf("input slice was mutated: %s", prefixes(in))
}
}
// TestDistinctBatchSpecs_CountsIntersectingSpecs verifies the batch
// pool-raise sizing counts only enabled, available specs whose languages
// are actually present in the batch.
func TestDistinctBatchSpecs_CountsIntersectingSpecs(t *testing.T) {
a := &Indexer{repoPrefix: "a"}
b := &Indexer{repoPrefix: "b"}
langSets := map[*Indexer][]string{
a: {"go"},
b: {"typescript"},
}
router := &dispatchFakeRouter{
enabled: []string{"gopls", "tsserver", "rust-analyzer", "gopls-broken"},
available: map[string]bool{"gopls": true, "tsserver": true, "rust-analyzer": true, "gopls-broken": false},
languages: map[string][]string{
"gopls": {"go"},
"tsserver": {"typescript", "javascript"},
"rust-analyzer": {"rust"},
"gopls-broken": {"go"},
},
}
// go → gopls, typescript → tsserver; rust-analyzer has no present
// language; gopls-broken is unavailable. So 2 distinct specs.
if got := distinctBatchSpecs(langSets, router); got != 2 {
t.Fatalf("distinctBatchSpecs = %d, want 2", got)
}
// Empty language sets → no specs.
if got := distinctBatchSpecs(map[*Indexer][]string{a: nil}, router); got != 0 {
t.Fatalf("distinctBatchSpecs(empty) = %d, want 0", got)
}
}
func prefixes(idxs []*Indexer) string {
out := "["
for i, idx := range idxs {
if i > 0 {
out += " "
}
out += idx.repoPrefix
}
return out + "]"
}
// dispatchFakeRouter is a minimal semantic.LSPRouter for exercising the
// batch dispatch helpers without spawning real LSP subprocesses.
type dispatchFakeRouter struct {
enabled []string
available map[string]bool
languages map[string][]string
maxAlive int
evictions uint64
}
func (f *dispatchFakeRouter) EnabledSpecNames() []string { return f.enabled }
func (f *dispatchFakeRouter) SpecAvailable(name string) bool { return f.available[name] }
func (f *dispatchFakeRouter) SpecLanguages(n string) []string { return f.languages[n] }
func (f *dispatchFakeRouter) SpecPriority(string) int { return 0 }
func (f *dispatchFakeRouter) ProviderForSpec(string) (semantic.Provider, error) {
return nil, nil
}
func (f *dispatchFakeRouter) ProviderForSpecWorkspace(string, string) (semantic.Provider, error) {
return nil, nil
}
func (f *dispatchFakeRouter) ReleaseSpecWorkspace(string, string) {}
func (f *dispatchFakeRouter) MaxAlive() int { return f.maxAlive }
func (f *dispatchFakeRouter) SetMaxAlive(n int) { f.maxAlive = n }
func (f *dispatchFakeRouter) EvictionCount() uint64 { return f.evictions }
func (f *dispatchFakeRouter) Close() error { return nil }