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,126 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/zzet/gortex/internal/graph"
|
||||
)
|
||||
|
||||
// seedWarmCacheGraph builds a graph with enough distinct ids and shared names
|
||||
// to push the parallel warm-cache helpers past their single-batch threshold
|
||||
// (minLookupWarmBatch) and to exercise the per-name []*Node bucketing that the
|
||||
// batch merge must preserve. Returns the graph plus the full id / name key
|
||||
// sets the helpers will be asked to load.
|
||||
func seedWarmCacheGraph(t *testing.T, n int) (graph.Store, []string, []string) {
|
||||
t.Helper()
|
||||
g := graph.New()
|
||||
ids := make([]string, 0, n)
|
||||
nameSet := make(map[string]struct{})
|
||||
for i := 0; i < n; i++ {
|
||||
// ~4 nodes share each name so the name lookup returns multi-element
|
||||
// buckets — the case the merge must not reorder or drop.
|
||||
name := fmt.Sprintf("sym%d", i%(n/4))
|
||||
id := fmt.Sprintf("pkg/f%d.go::%s", i, name)
|
||||
g.AddNode(&graph.Node{
|
||||
ID: id,
|
||||
Kind: graph.KindFunction,
|
||||
Name: name,
|
||||
FilePath: fmt.Sprintf("pkg/f%d.go", i),
|
||||
})
|
||||
ids = append(ids, id)
|
||||
nameSet[name] = struct{}{}
|
||||
}
|
||||
names := make([]string, 0, len(nameSet))
|
||||
for nm := range nameSet {
|
||||
names = append(names, nm)
|
||||
}
|
||||
return g, ids, names
|
||||
}
|
||||
|
||||
// TestWarmCacheParallel_GetNodesByIDsMatchesSerial pins the parallel id-batch
|
||||
// helper to the serial Store call on a seeded fixture: the merged result must
|
||||
// be byte-identical (same nodes, same absent keys for the injected misses).
|
||||
func TestWarmCacheParallel_GetNodesByIDsMatchesSerial(t *testing.T) {
|
||||
g, ids, _ := seedWarmCacheGraph(t, 6000)
|
||||
// Interleave ids that don't exist so both paths agree on absent keys.
|
||||
query := make([]string, 0, len(ids)+4)
|
||||
query = append(query, ids...)
|
||||
query = append(query, "pkg/missing1.go::ghost", "pkg/missing2.go::ghost", "", "pkg/f0.go::sym0")
|
||||
|
||||
require.Greater(t, lookupWarmBatches(len(query)), 0)
|
||||
|
||||
r := New(g)
|
||||
serial := g.GetNodesByIDs(query)
|
||||
parallel := r.parallelGetNodesByIDs(query)
|
||||
|
||||
assert.Equal(t, serial, parallel)
|
||||
assert.Len(t, parallel, len(ids)) // every real id present, ghosts + "" absent
|
||||
}
|
||||
|
||||
// TestWarmCacheParallel_FindNodesByNamesMatchesSerial pins the parallel
|
||||
// name-batch helper to the serial Store call, including the multi-node buckets
|
||||
// and the injected missing names.
|
||||
func TestWarmCacheParallel_FindNodesByNamesMatchesSerial(t *testing.T) {
|
||||
g, _, names := seedWarmCacheGraph(t, 6000)
|
||||
query := make([]string, 0, len(names)+3)
|
||||
query = append(query, names...)
|
||||
query = append(query, "nosuchname_a", "nosuchname_b", "")
|
||||
|
||||
r := New(g)
|
||||
serial := g.FindNodesByNames(query)
|
||||
parallel := r.parallelFindNodesByNames(query)
|
||||
|
||||
assert.Equal(t, serial, parallel)
|
||||
// Each present name bucketed all four of its nodes.
|
||||
for _, nm := range names {
|
||||
assert.Len(t, parallel[nm], 4, "name %q", nm)
|
||||
}
|
||||
_, missA := parallel["nosuchname_a"]
|
||||
assert.False(t, missA, "absent name must not appear in the result")
|
||||
}
|
||||
|
||||
// TestWarmCacheParallel_WarmLookupCacheContents drives the full warmLookupCache
|
||||
// over a seeded pending set and checks the assembled caches: every endpoint id
|
||||
// and target name is present (or recorded as an authoritative negative), which
|
||||
// is exactly what the parallel batching must preserve for the worker fast path.
|
||||
func TestWarmCacheParallel_WarmLookupCacheContents(t *testing.T) {
|
||||
g, ids, _ := seedWarmCacheGraph(t, 6000)
|
||||
|
||||
// One pending call edge per node, each From an existing node and To a bare
|
||||
// unresolved target name. Half the targets exist as node names, half don't
|
||||
// (authoritative negatives).
|
||||
pending := make([]*graph.Edge, 0, len(ids))
|
||||
for i, id := range ids {
|
||||
target := fmt.Sprintf("sym%d", i%(len(ids)/4))
|
||||
if i%2 == 0 {
|
||||
target = fmt.Sprintf("ghost%d", i) // no such node
|
||||
}
|
||||
pending = append(pending, &graph.Edge{
|
||||
From: id,
|
||||
To: "unresolved::" + target,
|
||||
Kind: graph.EdgeCalls,
|
||||
})
|
||||
}
|
||||
|
||||
r := New(g)
|
||||
r.warmLookupCache(pending)
|
||||
defer r.clearLookupCache()
|
||||
|
||||
// Every edge endpoint id is cached to its node.
|
||||
for _, id := range ids {
|
||||
n, ok := r.nodeByID[id]
|
||||
require.True(t, ok, "id %q missing from warm id cache", id)
|
||||
require.NotNil(t, n)
|
||||
assert.Equal(t, id, n.ID)
|
||||
}
|
||||
// Existing target names resolve; ghost names are cached as authoritative
|
||||
// negatives (present key, nil/empty slice) so the worker never falls
|
||||
// through to a per-edge store scan.
|
||||
assert.NotEmpty(t, r.nodesByName["sym1"])
|
||||
neg, ok := r.nodesByName["ghost0"]
|
||||
require.True(t, ok, "authoritative negative must be recorded for a missing target name")
|
||||
assert.Empty(t, neg)
|
||||
}
|
||||
Reference in New Issue
Block a user