package mesh import ( "encoding/json" "testing" "time" ) func TestFabricRouteSetForPeerEndpointCandidatesPrefersLocalLAN(t *testing.T) { metadata, _ := json.Marshal(FabricCandidateMetadata{LocalityGroupID: "home-lan", NATGroupID: "nat-a"}) routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{ { EndpointID: "node-b-public", NodeID: "node-b", Transport: "quic", Address: "quic://203.0.113.10:19443", Reachability: "public", ConnectivityMode: "direct", Priority: 10, }, { EndpointID: "node-b-lan", NodeID: "node-b", Transport: "quic", Address: "quic://10.10.0.12:19443", Reachability: "private", ConnectivityMode: "direct", PolicyTags: []string{"private-lan"}, Metadata: metadata, }, }, FabricRoutePlannerConfig{ ClusterID: "cluster-1", LocalNodeID: "node-a", LocalityGroupID: "home-lan", DefaultCapacity: 200, Now: time.Unix(100, 0).UTC(), }) if routeSet.Primary.RouteID != "node-b-lan" { t.Fatalf("primary route = %q, want node-b-lan", routeSet.Primary.RouteID) } if routeSet.Primary.Hops[len(routeSet.Primary.Hops)-1].Mode != FabricRouteLAN { t.Fatalf("primary mode = %q, want lan", routeSet.Primary.Hops[len(routeSet.Primary.Hops)-1].Mode) } } func TestFabricRouteSetForPeerEndpointCandidatesBuildsRelayFallback(t *testing.T) { metadata, _ := json.Marshal(struct { FabricCandidateMetadata TLSCertSHA256 string `json:"tls_cert_sha256,omitempty"` }{ FabricCandidateMetadata: FabricCandidateMetadata{RelayNodeID: "node-r", RelayEndpoint: "quic://node-r:19443"}, TLSCertSHA256: "relay-cert", }) routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{{ EndpointID: "node-b-relay", NodeID: "node-b", Transport: "quic", Address: "quic://node-b-passive:19443", Reachability: "outbound_only", ConnectivityMode: "relay_required", NATType: "symmetric", Metadata: metadata, }}, FabricRoutePlannerConfig{ ClusterID: "cluster-1", LocalNodeID: "node-a", RelayCapacity: 50, Now: time.Unix(100, 0).UTC(), }) if routeSet.Primary.RouteID != "node-b-relay" { t.Fatalf("primary route = %q", routeSet.Primary.RouteID) } if routeSet.Primary.RelayCount != 2 { t.Fatalf("relay count = %d, want 2", routeSet.Primary.RelayCount) } if got := routeSet.Primary.Hops[1].NodeID; got != "node-r" { t.Fatalf("relay hop = %q, want node-r", got) } if got := routeSet.Primary.Hops[1].PeerCertSHA256; got != "relay-cert" { t.Fatalf("relay hop peer cert = %q, want relay-cert", got) } if routeSet.Primary.Capacity != 50 { t.Fatalf("capacity = %d, want 50", routeSet.Primary.Capacity) } } func TestFabricRouteSetForPeerEndpointCandidatesUsesTargetWhenRelayMetadataIsAbsent(t *testing.T) { routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{{ EndpointID: "node-b-relay", NodeID: "node-b", Transport: "relay_quic", Address: "quic://node-b:19443", Reachability: "relay", ConnectivityMode: "relay_required", Metadata: json.RawMessage(`{"tls_cert_sha256":"abc123"}`), }}, FabricRoutePlannerConfig{ClusterID: "cluster-1", LocalNodeID: "node-a"}) if routeSet.Primary.RouteID != "node-b-relay" { t.Fatalf("primary route = %q", routeSet.Primary.RouteID) } if len(routeSet.Primary.Hops) != 2 { t.Fatalf("hops = %+v, want local + target only", routeSet.Primary.Hops) } targetHop := routeSet.Primary.Hops[1] if targetHop.NodeID != "node-b" || targetHop.Mode != FabricRouteRelay || targetHop.PeerCertSHA256 != "abc123" { t.Fatalf("target hop = %+v, want relay-mode target with cert", targetHop) } } func TestFabricRouteSetForPeerEndpointCandidatesAcceptsExplicitQUICModes(t *testing.T) { for _, tc := range []struct { name string transport string wantMode FabricRouteMode }{ {name: "lan", transport: "lan_quic", wantMode: FabricRouteLAN}, {name: "reverse", transport: "reverse_quic", wantMode: FabricRouteReverse}, {name: "relay", transport: "relay_quic", wantMode: FabricRouteRelay}, {name: "ice", transport: "ice_quic", wantMode: FabricRouteICE}, } { t.Run(tc.name, func(t *testing.T) { routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{{ EndpointID: "node-b-" + tc.name, NodeID: "node-b", Transport: tc.transport, Address: "quic://node-b:19443", Reachability: "private", ConnectivityMode: "direct", Metadata: json.RawMessage(`{"tls_cert_sha256":"abc123"}`), }}, FabricRoutePlannerConfig{ClusterID: "cluster-1", LocalNodeID: "node-a"}) if routeSet.Primary.RouteID == "" { t.Fatalf("%s candidate produced empty route set", tc.transport) } hop := routeSet.Primary.Hops[len(routeSet.Primary.Hops)-1] if hop.Mode != tc.wantMode { t.Fatalf("mode = %q, want %q", hop.Mode, tc.wantMode) } if hop.PeerCertSHA256 != "abc123" { t.Fatalf("peer cert = %q, want abc123", hop.PeerCertSHA256) } }) } } func TestFabricRouteSetForPeerEndpointCandidatesTreatsSameNATGroupAsLAN(t *testing.T) { metadata, _ := json.Marshal(FabricCandidateMetadata{NATGroupID: "nat-a"}) routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{{ EndpointID: "node-b-nat-lan", NodeID: "node-b", Transport: "quic", Address: "quic://10.44.0.12:19443", Reachability: "private", ConnectivityMode: "direct", NATType: "symmetric", Metadata: metadata, }}, FabricRoutePlannerConfig{ ClusterID: "cluster-1", LocalNodeID: "node-a", LocalNATGroupID: "nat-a", }) if routeSet.Primary.Hops[len(routeSet.Primary.Hops)-1].Mode != FabricRouteLAN { t.Fatalf("route = %+v, want LAN mode for same NAT group", routeSet.Primary) } } func TestFabricRouteSetForPeerEndpointCandidatesRejectsNonQUIC(t *testing.T) { for _, candidate := range []PeerEndpointCandidate{ { EndpointID: "node-b-http", NodeID: "node-b", Transport: "direct_http", Address: "http://node-b:8080", Reachability: "public", ConnectivityMode: "direct", }, { EndpointID: "node-b-compat-relay", NodeID: "node-b", Transport: "relay", Address: "quic://node-r:19443", Reachability: "relay", ConnectivityMode: "relay_required", }, { EndpointID: "node-b-compat-reverse", NodeID: "node-b", Transport: "outbound_reverse", Address: "quic://node-b:19443", Reachability: "outbound_only", ConnectivityMode: "outbound_only", }, } { routeSet := FabricRouteSetForPeerEndpointCandidates("node-b", []PeerEndpointCandidate{candidate}, FabricRoutePlannerConfig{ClusterID: "cluster-1", LocalNodeID: "node-a"}) if routeSet.Primary.RouteID != "" || len(routeSet.WarmStandby) != 0 { t.Fatalf("non-quic candidate produced route set: %+v", routeSet) } } }