235 lines
7.4 KiB
Go
235 lines
7.4 KiB
Go
package mesh
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestPeerConnectionIntentsClassifyCorporateDirect(t *testing.T) {
|
|
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
|
|
plan := PlanPeerConnectionIntents(PeerConnectionIntentPlanConfig{
|
|
PeerCache: PeerCacheSnapshot{Entries: []PeerCacheEntry{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "http://10.24.10.20:19001",
|
|
BestTransport: "direct_tcp_tls",
|
|
BestReachability: "private",
|
|
BestConnectivity: "direct",
|
|
BestPolicyTags: []string{"corp-lan", "same-site"},
|
|
},
|
|
}},
|
|
RecoveryPlan: PeerRecoveryPlan{
|
|
Mode: PeerRecoveryModeSteady,
|
|
Candidates: []PeerRecoveryCandidate{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "http://10.24.10.20:19001",
|
|
ConnectionState: PeerConnectionReady,
|
|
Reason: "maintain_ready",
|
|
Priority: 100,
|
|
},
|
|
},
|
|
},
|
|
Now: now,
|
|
})
|
|
|
|
if plan.IntentCount != 1 || plan.MaintainCount != 1 || plan.CorporateLANCount != 1 {
|
|
t.Fatalf("unexpected plan counts: %+v", plan)
|
|
}
|
|
intent := plan.Intents[0]
|
|
if intent.Action != PeerConnectionIntentMaintain || intent.TransportMode != PeerTransportModeCorporateLAN || intent.RequiresRendezvous {
|
|
t.Fatalf("unexpected corporate intent: %+v", intent)
|
|
}
|
|
}
|
|
|
|
func TestPeerConnectionIntentsClassifyOutboundAndRelayAsRendezvousRequired(t *testing.T) {
|
|
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
|
|
plan := PlanPeerConnectionIntents(PeerConnectionIntentPlanConfig{
|
|
PeerCache: PeerCacheSnapshot{Entries: []PeerCacheEntry{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "https://node-b.example.test:443",
|
|
BestTransport: "direct_tcp_tls",
|
|
BestReachability: "outbound_only",
|
|
BestConnectivity: "outbound_only",
|
|
},
|
|
{
|
|
NodeID: "node-c",
|
|
Endpoint: "relay://fabric-relay/node-c",
|
|
BestTransport: "relay",
|
|
BestReachability: "relay",
|
|
BestConnectivity: "relay_required",
|
|
},
|
|
}},
|
|
RecoveryPlan: PeerRecoveryPlan{
|
|
Mode: PeerRecoveryModeRecovery,
|
|
Candidates: []PeerRecoveryCandidate{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "https://node-b.example.test:443",
|
|
ConnectionState: PeerConnectionDisconnected,
|
|
Reason: "recover_warm",
|
|
Priority: 90,
|
|
},
|
|
{
|
|
NodeID: "node-c",
|
|
Endpoint: "relay://fabric-relay/node-c",
|
|
ConnectionState: PeerConnectionDisconnected,
|
|
Reason: "recover_seed",
|
|
Priority: 80,
|
|
},
|
|
},
|
|
},
|
|
Now: now,
|
|
})
|
|
|
|
if plan.RecoverCount != 2 || plan.OutboundOnlyCount != 1 || plan.RelayRequiredCount != 1 || plan.RendezvousRequiredCount != 2 {
|
|
t.Fatalf("unexpected rendezvous counts: %+v", plan)
|
|
}
|
|
if plan.Intents[0].Action != PeerConnectionIntentRecover || plan.Intents[1].Action != PeerConnectionIntentRecover {
|
|
t.Fatalf("unexpected actions: %+v", plan.Intents)
|
|
}
|
|
}
|
|
|
|
func TestPeerConnectionIntentsResolveRendezvousWithRelayLease(t *testing.T) {
|
|
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
|
|
plan := PlanPeerConnectionIntents(PeerConnectionIntentPlanConfig{
|
|
PeerCache: PeerCacheSnapshot{Entries: []PeerCacheEntry{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "relay://fabric/node-b",
|
|
BestTransport: "relay",
|
|
BestReachability: "relay",
|
|
BestConnectivity: "relay_required",
|
|
},
|
|
}},
|
|
RecoveryPlan: PeerRecoveryPlan{
|
|
Mode: PeerRecoveryModeRecovery,
|
|
Candidates: []PeerRecoveryCandidate{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "relay://fabric/node-b",
|
|
ConnectionState: PeerConnectionDisconnected,
|
|
Reason: "recover_warm",
|
|
Priority: 100,
|
|
},
|
|
},
|
|
},
|
|
RendezvousLeases: []PeerRendezvousLease{
|
|
{
|
|
LeaseID: "lease-node-b-via-node-r",
|
|
PeerNodeID: "node-b",
|
|
RelayNodeID: "node-r",
|
|
RelayEndpoint: "http://node-r:19000",
|
|
Transport: "relay_control",
|
|
ConnectivityMode: "relay_required",
|
|
Priority: 10,
|
|
ControlPlaneOnly: true,
|
|
IssuedAt: now.Add(-time.Minute),
|
|
ExpiresAt: now.Add(time.Minute),
|
|
},
|
|
},
|
|
Now: now,
|
|
})
|
|
|
|
if plan.IntentCount != 1 || plan.RelayControlCount != 1 || plan.RendezvousResolvedCount != 1 || plan.RendezvousRequiredCount != 0 {
|
|
t.Fatalf("unexpected relay-control plan counts: %+v", plan)
|
|
}
|
|
intent := plan.Intents[0]
|
|
if intent.TransportMode != PeerTransportModeRelayControl ||
|
|
intent.Endpoint != "http://node-r:19000" ||
|
|
intent.RelayNodeID != "node-r" ||
|
|
intent.RendezvousLeaseID != "lease-node-b-via-node-r" ||
|
|
!intent.RelayCandidate ||
|
|
!intent.RendezvousResolved ||
|
|
intent.RequiresRendezvous {
|
|
t.Fatalf("unexpected resolved rendezvous intent: %+v", intent)
|
|
}
|
|
}
|
|
|
|
func TestPeerConnectionIntentsSkipExpiredRendezvousLeaseAndReselect(t *testing.T) {
|
|
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
|
|
plan := PlanPeerConnectionIntents(PeerConnectionIntentPlanConfig{
|
|
PeerCache: PeerCacheSnapshot{Entries: []PeerCacheEntry{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "relay://fabric/node-b",
|
|
BestTransport: "relay",
|
|
BestReachability: "relay",
|
|
BestConnectivity: "relay_required",
|
|
},
|
|
}},
|
|
RecoveryPlan: PeerRecoveryPlan{
|
|
Mode: PeerRecoveryModeRecovery,
|
|
Candidates: []PeerRecoveryCandidate{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "relay://fabric/node-b",
|
|
ConnectionState: PeerConnectionWaiting,
|
|
Reason: "recover_warm",
|
|
Priority: 100,
|
|
},
|
|
},
|
|
},
|
|
RendezvousLeases: []PeerRendezvousLease{
|
|
{
|
|
LeaseID: "lease-expired-preferred",
|
|
PeerNodeID: "node-b",
|
|
RelayNodeID: "node-r-old",
|
|
RelayEndpoint: "http://node-r-old:19000",
|
|
Transport: "relay_control",
|
|
ConnectivityMode: "relay_required",
|
|
Priority: 1,
|
|
ControlPlaneOnly: true,
|
|
IssuedAt: now.Add(-10 * time.Minute),
|
|
ExpiresAt: now.Add(-time.Second),
|
|
},
|
|
{
|
|
LeaseID: "lease-active-reselected",
|
|
PeerNodeID: "node-b",
|
|
RelayNodeID: "node-r-new",
|
|
RelayEndpoint: "http://node-r-new:19000",
|
|
Transport: "relay_control",
|
|
ConnectivityMode: "relay_required",
|
|
Priority: 20,
|
|
ControlPlaneOnly: true,
|
|
IssuedAt: now.Add(-time.Minute),
|
|
ExpiresAt: now.Add(time.Minute),
|
|
},
|
|
},
|
|
Now: now,
|
|
})
|
|
|
|
if plan.RendezvousResolvedCount != 1 || plan.RelayControlCount != 1 || plan.RendezvousRequiredCount != 0 {
|
|
t.Fatalf("unexpected reselected plan counts: %+v", plan)
|
|
}
|
|
intent := plan.Intents[0]
|
|
if intent.RendezvousLeaseID != "lease-active-reselected" ||
|
|
intent.RelayNodeID != "node-r-new" ||
|
|
intent.Endpoint != "http://node-r-new:19000" {
|
|
t.Fatalf("expired lease was not skipped: %+v", intent)
|
|
}
|
|
}
|
|
|
|
func TestPeerConnectionIntentsClassifyPrivateEndpointWithoutCandidateHints(t *testing.T) {
|
|
plan := PlanPeerConnectionIntents(PeerConnectionIntentPlanConfig{
|
|
PeerCache: PeerCacheSnapshot{Entries: []PeerCacheEntry{
|
|
{NodeID: "node-b", Endpoint: "http://192.168.10.20:19001"},
|
|
}},
|
|
RecoveryPlan: PeerRecoveryPlan{Candidates: []PeerRecoveryCandidate{
|
|
{
|
|
NodeID: "node-b",
|
|
Endpoint: "http://192.168.10.20:19001",
|
|
ConnectionState: PeerConnectionDisconnected,
|
|
Reason: "recover_peer",
|
|
Priority: 10,
|
|
},
|
|
}},
|
|
Now: time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC),
|
|
})
|
|
|
|
if plan.PrivateLANCount != 1 || plan.Intents[0].TransportMode != PeerTransportModePrivateLAN || !plan.Intents[0].DirectCandidate {
|
|
t.Fatalf("unexpected private endpoint classification: %+v", plan)
|
|
}
|
|
}
|