package mesh import ( "testing" "time" ) func TestPeerCacheSelectsAdjacentWarmPeersWithinLimit(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-b"} cache := NewPeerCache(PeerCacheConfig{ Local: local, PeerEndpoints: map[string]string{ "node-a": "quic://node-a:19443", "node-r": "quic://node-r:19443", "node-c": "quic://node-c:19443", }, Routes: []SyntheticRoute{ peerCacheRoute("route-1", []string{"node-a", local.NodeID, "node-r", "node-c"}), }, RecoverySeeds: []PeerRecoverySeed{ {NodeID: "node-seed", Endpoint: "quic://seed.example.test:19443", Transport: "direct_quic", Priority: 10}, }, WarmPeerLimit: 2, Now: time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC), }) warm := cache.WarmPeerIDs() if len(warm) != 2 || warm[0] != "node-a" || warm[1] != "node-r" { t.Fatalf("warm peers = %+v, want adjacent node-a/node-r", warm) } snapshot := cache.Snapshot() if snapshot.PeerCount != 4 || snapshot.RecoverySeedCount != 1 { t.Fatalf("unexpected snapshot counts: %+v", snapshot) } } func TestPeerCachePromotesRecoverySeedAfterRoutePeers(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-b"} cache := NewPeerCache(PeerCacheConfig{ Local: local, Routes: []SyntheticRoute{ peerCacheRoute("route-1", []string{"node-a", local.NodeID, "node-r"}), }, RecoverySeeds: []PeerRecoverySeed{ {NodeID: "node-seed", Endpoint: "quic://seed.example.test:19443", Transport: "direct_quic", ConnectivityMode: "direct", Priority: 1}, }, WarmPeerLimit: 3, Now: time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC), }) warm := cache.WarmPeerIDs() if len(warm) != 3 || warm[0] != "node-a" || warm[1] != "node-r" || warm[2] != "node-seed" { t.Fatalf("warm peers = %+v, want adjacent peers then seed", warm) } seed, ok := peerCacheEntryByID(cache.Snapshot(), "node-seed") if !ok || !seed.RecoverySeed || seed.WarmReason != "recovery_seed" { t.Fatalf("unexpected seed entry: %+v", seed) } } func TestPeerCacheUsesBestEndpointCandidate(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"} now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC) cache := NewPeerCache(PeerCacheConfig{ Local: local, PeerEndpointCandidates: map[string][]PeerEndpointCandidate{ "node-b": { { EndpointID: "node-b-relay", NodeID: "node-b", Transport: "relay_quic", Address: "relay.example.test", Reachability: "relay", ConnectivityMode: "relay_required", Priority: 20, }, { EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_quic", Address: "quic://203.0.113.20:19443", Reachability: "public", NATType: "none", ConnectivityMode: "direct", Priority: 1, LastVerifiedAt: &now, }, }, }, WarmPeerLimit: 1, Now: now, }) entry, ok := peerCacheEntryByID(cache.Snapshot(), "node-b") if !ok { t.Fatal("node-b missing from cache") } if entry.BestCandidateID != "node-b-public" || !entry.Warm { t.Fatalf("unexpected candidate selection: %+v", entry) } if entry.PublicIngressCount != 1 { t.Fatalf("public ingress count = %d, want 1", entry.PublicIngressCount) } } func TestPeerCacheAppliesEndpointHealthObservations(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"} now := time.Date(2026, 5, 16, 12, 0, 0, 0, time.UTC) cache := NewPeerCache(PeerCacheConfig{ Local: local, PeerEndpointCandidates: map[string][]PeerEndpointCandidate{ "node-b": { { EndpointID: "node-b-quic", NodeID: "node-b", Transport: "direct_quic", Address: "quic://node-b.example.test:19443", Reachability: "public", NATType: "none", ConnectivityMode: "direct", Priority: 1, LastVerifiedAt: &now, }, { EndpointID: "node-b-ice", NodeID: "node-b", Transport: "ice_quic", Address: "quic://node-b.example.test:19444", Reachability: "public", NATType: "none", ConnectivityMode: "direct", Priority: 1, LastVerifiedAt: &now, }, }, }, PeerEndpointObservations: map[string]EndpointCandidateHealthObservation{ "node-b-quic": { EndpointID: "node-b-quic", FailureCount: 2, LastFailureReason: "session_open_failed", ReliabilityScore: 35, ObservedAt: now, }, }, WarmPeerLimit: 1, Now: now, }) entry, ok := peerCacheEntryByID(cache.Snapshot(), "node-b") if !ok { t.Fatal("node-b missing from cache") } if entry.BestCandidateID != "node-b-ice" || entry.Endpoint != "quic://node-b.example.test:19444" { t.Fatalf("peer cache did not apply endpoint observations: %+v", entry) } if !containsString(entry.BestScoreReasons, "transport:ice_quic") { t.Fatalf("peer cache did not expose score reasons: %+v", entry.BestScoreReasons) } } func TestPeerCacheUsesPreferredCorporateEndpointAddress(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"} cache := NewPeerCache(PeerCacheConfig{ Local: local, PeerEndpoints: map[string]string{ "node-b": "quic://node-b.public.example.test:19443", }, PeerEndpointCandidates: map[string][]PeerEndpointCandidate{ "node-b": { { EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_quic", Address: "quic://node-b.public.example.test:19443", Reachability: "public", NATType: "none", ConnectivityMode: "direct", Region: "corp-eu", Priority: 10, }, { EndpointID: "node-b-corp-lan", NodeID: "node-b", Transport: "lan_quic", Address: "quic://10.24.10.20:19443", Reachability: "private", NATType: "none", ConnectivityMode: "direct", Region: "corp-eu", Priority: 1, PolicyTags: []string{"corp-lan"}, }, }, }, PreferredRegion: "corp-eu", WarmPeerLimit: 1, Now: time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC), }) entry, ok := peerCacheEntryByID(cache.Snapshot(), "node-b") if !ok { t.Fatal("node-b missing from peer cache") } if entry.BestCandidateID != "node-b-corp-lan" || entry.Endpoint != "quic://10.24.10.20:19443" { t.Fatalf("peer cache did not choose corp LAN endpoint: %+v", entry) } } func peerCacheRoute(routeID string, hops []string) SyntheticRoute { return SyntheticRoute{ RouteID: routeID, ClusterID: "cluster-1", SourceNodeID: hops[0], DestinationNodeID: hops[len(hops)-1], Hops: append([]string{}, hops...), AllowedChannels: []string{SyntheticChannelFabricControl}, ExpiresAt: time.Now().UTC().Add(time.Hour), } } func peerCacheEntryByID(snapshot PeerCacheSnapshot, nodeID string) (PeerCacheEntry, bool) { for _, entry := range snapshot.Entries { if entry.NodeID == nodeID { return entry, true } } return PeerCacheEntry{}, false } func containsString(values []string, want string) bool { for _, value := range values { if value == want { return true } } return false }