mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-08 09:49:54 +00:00
831 lines
18 KiB
Go
831 lines
18 KiB
Go
package client
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/netbirdio/netbird/client/internal/peer"
|
|
"github.com/netbirdio/netbird/client/internal/routemanager/common"
|
|
"github.com/netbirdio/netbird/client/internal/routemanager/static"
|
|
"github.com/netbirdio/netbird/route"
|
|
)
|
|
|
|
func TestGetBestrouteFromStatuses(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
statuses map[route.ID]routerPeerStatus
|
|
expectedRouteID route.ID
|
|
currentRoute route.ID
|
|
existingRoutes map[route.ID]*route.Route
|
|
}{
|
|
{
|
|
name: "one route",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "one connected routes with relayed and direct",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "one connected routes with relayed and no direct",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "no connected peers",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "",
|
|
},
|
|
{
|
|
name: "multiple connected peers with different metrics",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: 9000,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "multiple connected peers with one relayed",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "multiple connected peers with different latencies",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
latency: 300 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "should ignore routes with latency 0",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "current route with similar score and similar but slightly worse latency should not change",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 15 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "route1",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "relayed routes with latency 0 should maintain previous choice",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "route1",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "p2p routes with latency 0 should maintain previous choice",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "route1",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "current route with bad score should be changed to route with better score",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 200 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "route1",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "current chosen route doesn't exist anymore",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 20 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "routeDoesntExistAnymore",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "connected peer should be preferred over idle peer",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 100 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "idle peer should be selected when no connected peers",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 5 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "best idle peer should be selected among multiple idle peers",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 100 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "connecting peers should not be considered for routing",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 5 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "",
|
|
},
|
|
{
|
|
name: "mixed statuses - connected wins over idle and connecting",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 5 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route3": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
latency: 200 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
"route3": {
|
|
ID: "route3",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer3",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route3",
|
|
},
|
|
{
|
|
name: "idle peer with better metric should win over idle peer with worse metric",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 50 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 50 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: 5000,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "current idle route should be maintained for similar scores",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 20 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 15 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "route1",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "idle peer with zero latency should still be considered",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 0 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "direct idle peer preferred over relayed idle peer",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: true,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 50 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "connected peer with worse metric still beats idle peer with better metric",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 50 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: 1000,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "connected peer wins even when idle peer has all advantages",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 1 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: true,
|
|
latency: 30 * time.Minute,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: 1,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "connected peer should be preferred over idle peer",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnected,
|
|
relayed: false,
|
|
latency: 100 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
{
|
|
name: "idle peer should be selected when no connected peers",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusConnecting,
|
|
relayed: false,
|
|
latency: 5 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route1",
|
|
},
|
|
{
|
|
name: "best idle peer should be selected among multiple idle peers",
|
|
statuses: map[route.ID]routerPeerStatus{
|
|
"route1": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 100 * time.Millisecond,
|
|
},
|
|
"route2": {
|
|
status: peer.StatusIdle,
|
|
relayed: false,
|
|
latency: 10 * time.Millisecond,
|
|
},
|
|
},
|
|
existingRoutes: map[route.ID]*route.Route{
|
|
"route1": {
|
|
ID: "route1",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer1",
|
|
},
|
|
"route2": {
|
|
ID: "route2",
|
|
Metric: route.MaxMetric,
|
|
Peer: "peer2",
|
|
},
|
|
},
|
|
currentRoute: "",
|
|
expectedRouteID: "route2",
|
|
},
|
|
}
|
|
|
|
// fill the test data with random routes
|
|
for _, tc := range testCases {
|
|
for i := 0; i < 50; i++ {
|
|
dummyRoute := &route.Route{
|
|
ID: route.ID(fmt.Sprintf("dummy_p1_%d", i)),
|
|
Metric: route.MinMetric,
|
|
Peer: fmt.Sprintf("dummy_p1_%d", i),
|
|
}
|
|
tc.existingRoutes[dummyRoute.ID] = dummyRoute
|
|
}
|
|
for i := 0; i < 50; i++ {
|
|
dummyRoute := &route.Route{
|
|
ID: route.ID(fmt.Sprintf("dummy_p2_%d", i)),
|
|
Metric: route.MinMetric,
|
|
Peer: fmt.Sprintf("dummy_p1_%d", i),
|
|
}
|
|
tc.existingRoutes[dummyRoute.ID] = dummyRoute
|
|
}
|
|
|
|
for i := 0; i < 50; i++ {
|
|
id := route.ID(fmt.Sprintf("dummy_p1_%d", i))
|
|
dummyStatus := routerPeerStatus{
|
|
status: peer.StatusConnecting,
|
|
relayed: true,
|
|
latency: 0,
|
|
}
|
|
tc.statuses[id] = dummyStatus
|
|
}
|
|
for i := 0; i < 50; i++ {
|
|
id := route.ID(fmt.Sprintf("dummy_p2_%d", i))
|
|
dummyStatus := routerPeerStatus{
|
|
status: peer.StatusConnecting,
|
|
relayed: true,
|
|
latency: 0,
|
|
}
|
|
tc.statuses[id] = dummyStatus
|
|
}
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
currentRoute := &route.Route{
|
|
ID: "routeDoesntExistAnymore",
|
|
}
|
|
if tc.currentRoute != "" {
|
|
currentRoute = tc.existingRoutes[tc.currentRoute]
|
|
}
|
|
|
|
params := common.HandlerParams{
|
|
Route: &route.Route{Network: netip.MustParsePrefix("192.168.0.0/24")},
|
|
}
|
|
// create new clientNetwork
|
|
client := &Watcher{
|
|
handler: static.NewRoute(params),
|
|
routes: tc.existingRoutes,
|
|
currentChosen: currentRoute,
|
|
}
|
|
|
|
chosenRoute, _ := client.getBestRouteFromStatuses(tc.statuses)
|
|
if chosenRoute != tc.expectedRouteID {
|
|
t.Errorf("expected routeID %s, got %s", tc.expectedRouteID, chosenRoute)
|
|
}
|
|
})
|
|
}
|
|
}
|