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": "http://node-a:19000", "node-r": "http://node-r:19000", "node-c": "http://node-c:19000", }, Routes: []SyntheticRoute{ peerCacheRoute("route-1", []string{"node-a", local.NodeID, "node-r", "node-c"}), }, RecoverySeeds: []PeerRecoverySeed{ {NodeID: "node-seed", Endpoint: "https://seed.example.test", Transport: "direct_tcp_tls", 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: "wss://seed.example.test/mesh", Transport: "wss", 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", Address: "relay.example.test", Reachability: "relay", ConnectivityMode: "relay_required", Priority: 20, }, { EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "203.0.113.20:443", 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) } } func TestPeerCacheUsesPreferredCorporateEndpointAddress(t *testing.T) { local := PeerIdentity{ClusterID: "cluster-1", NodeID: "node-a"} cache := NewPeerCache(PeerCacheConfig{ Local: local, PeerEndpoints: map[string]string{ "node-b": "https://node-b.public.example.test:443", }, PeerEndpointCandidates: map[string][]PeerEndpointCandidate{ "node-b": { { EndpointID: "node-b-public", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "https://node-b.public.example.test:443", Reachability: "public", NATType: "none", ConnectivityMode: "direct", Region: "corp-eu", Priority: 10, }, { EndpointID: "node-b-corp-lan", NodeID: "node-b", Transport: "direct_tcp_tls", Address: "http://10.24.10.20:19001", 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 != "http://10.24.10.20:19001" { 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 }