Files
zzet--gortex/internal/daemon/federation_merge_named_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

103 lines
3.9 KiB
Go

package daemon
import (
"context"
"encoding/json"
"testing"
"github.com/zzet/gortex/internal/graph"
"github.com/zzet/gortex/internal/query"
)
// TestFederator_MergeOriginsMap asserts the federated merge attaches a
// sibling origins map that tags which remote each merged node came from
// (and tags the local nodes "local").
func TestFederator_MergeOriginsMap(t *testing.T) {
remote := fakeRemote(t, fakeRemoteOpts{indexed: true, toolJSON: `{"nodes":[{"id":"r/x.go::RemoteOnly"},{"id":"shared::Sym"}],"edges":[],"total_nodes":2,"total_edges":0}`})
local := envelope(`{"nodes":[{"id":"shared::Sym"},{"id":"l/a.go::LocalOnly"}],"edges":[],"total_nodes":2,"total_edges":0}`)
out := testFederator().Augment(context.Background(), "find_usages", []byte(`{}`),
local, []ServerEntry{{Slug: "r2", URL: remote.URL}})
m := decodeFederated(t, out)
origins, ok := m["origins"].(map[string]any)
if !ok {
t.Fatalf("a federated merge must attach a sibling origins map, got %v", m["origins"])
}
// Every merged node id must be tagged with its provenance.
want := map[string]string{
"l/a.go::LocalOnly": "local",
"shared::Sym": "local", // local wins on collision
"r/x.go::RemoteOnly": "remote:r2",
}
for id, src := range want {
if origins[id] != src {
t.Errorf("origins[%q] = %v, want %q", id, origins[id], src)
}
}
if len(origins) != len(want) {
t.Errorf("origins map should tag exactly the %d merged nodes, got %d (%v)", len(want), len(origins), origins)
}
}
// TestFederator_DeepCopiesNodes asserts the merge works on detached
// copies of remote node data: mutating a node in one merged response must
// never bleed into a subsequent merge of the same remote, proving no
// stored *graph.Node pointer is aliased across responses.
func TestFederator_DeepCopiesNodes(t *testing.T) {
const remoteBody = `{"nodes":[{"id":"r/x.go::Caller","name":"OriginalName"}],"edges":[],"total_nodes":1,"total_edges":0}`
remote := fakeRemote(t, fakeRemoteOpts{indexed: true, toolJSON: remoteBody})
local := envelope(`{"nodes":[],"edges":[],"total_nodes":0,"total_edges":0}`)
fed := testFederator()
roster := []ServerEntry{{Slug: "r2", URL: remote.URL}}
// First fan-out: pull the remote node into a merged SubGraph and mutate
// it in place.
out1 := fed.Augment(context.Background(), "find_usages", []byte(`{}`), local, roster)
tool1, _ := unwrapToolJSON(out1)
var sg1 query.SubGraph
if err := json.Unmarshal(tool1, &sg1); err != nil {
t.Fatalf("decode first merged subgraph: %v", err)
}
caller1 := findNamedNode(&sg1, "r/x.go::Caller")
if caller1 == nil {
t.Fatal("first merge must carry the remote node")
}
if caller1.Name != "OriginalName" {
t.Fatalf("remote node name should round-trip, got %q", caller1.Name)
}
// Mutate the per-response node. If the federator aliased a shared,
// stored pointer this would corrupt the source of every later merge.
caller1.Name = "MUTATED"
// Second fan-out of the same remote: the node must still carry the
// original name, untouched by the first response's mutation.
out2 := fed.Augment(context.Background(), "find_usages", []byte(`{}`), local, roster)
tool2, _ := unwrapToolJSON(out2)
var sg2 query.SubGraph
if err := json.Unmarshal(tool2, &sg2); err != nil {
t.Fatalf("decode second merged subgraph: %v", err)
}
caller2 := findNamedNode(&sg2, "r/x.go::Caller")
if caller2 == nil {
t.Fatal("second merge must carry the remote node")
}
if caller2.Name != "OriginalName" {
t.Errorf("mutating a merged node must not bleed into a later response (deep copy): got %q, want %q",
caller2.Name, "OriginalName")
}
// And the two responses must not share the same node pointer.
if caller1 == caller2 {
t.Error("each federated response must hand back its own node, not a shared pointer")
}
}
func findNamedNode(sg *query.SubGraph, id string) *graph.Node {
for _, n := range sg.Nodes {
if n != nil && n.ID == id {
return n
}
}
return nil
}