mirror of https://github.com/coder/coder.git
658 lines
16 KiB
Go
658 lines
16 KiB
Go
package tailnet
|
|
|
|
import (
|
|
"net/netip"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/exp/maps"
|
|
"golang.org/x/exp/slices"
|
|
"golang.org/x/xerrors"
|
|
"tailscale.com/tailcfg"
|
|
"tailscale.com/types/key"
|
|
"tailscale.com/wgengine"
|
|
|
|
"cdr.dev/slog"
|
|
"cdr.dev/slog/sloggers/slogtest"
|
|
"github.com/coder/coder/v2/testutil"
|
|
)
|
|
|
|
func TestNodeUpdater_setNetInfo_different(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
goCh := make(chan struct{})
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
<-goCh
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
dl := map[string]float64{"1": 0.025}
|
|
uut.setNetInfo(&tailcfg.NetInfo{
|
|
PreferredDERP: 1,
|
|
DERPLatency: dl,
|
|
})
|
|
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Equal(t, 1, node.PreferredDERP)
|
|
require.True(t, maps.Equal(dl, node.DERPLatency))
|
|
|
|
// Send in second update to test getting updates in the middle of the
|
|
// callback
|
|
uut.setNetInfo(&tailcfg.NetInfo{
|
|
PreferredDERP: 2,
|
|
DERPLatency: dl,
|
|
})
|
|
close(goCh) // allows callback to complete
|
|
|
|
node = testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Equal(t, 2, node.PreferredDERP)
|
|
require.True(t, maps.Equal(dl, node.DERPLatency))
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setNetInfo_same(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP and latency already set
|
|
dl := map[string]float64{"1": 0.025}
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.derpLatency = maps.Clone(dl)
|
|
uut.L.Unlock()
|
|
|
|
// When: new update with same info
|
|
uut.setNetInfo(&tailcfg.NetInfo{
|
|
PreferredDERP: 1,
|
|
DERPLatency: dl,
|
|
})
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setDERPForcedWebsocket_different(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Given: preferred DERP is 1, so we'll send an update
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.L.Unlock()
|
|
|
|
// When: we set a new forced websocket reason
|
|
uut.setDERPForcedWebsocket(1, "test")
|
|
|
|
// Then: we receive an update with the reason set
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.True(t, maps.Equal(map[int]string{1: "test"}, node.DERPForcedWebsocket))
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setDERPForcedWebsocket_same(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change &&
|
|
// reason for region 1 is set to "test"
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.derpForcedWebsockets[1] = "test"
|
|
uut.L.Unlock()
|
|
|
|
// When: we set region 1 to "test
|
|
uut.setDERPForcedWebsocket(1, "test")
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setStatus_different(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Given: preferred DERP is 1, so we'll send an update
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.L.Unlock()
|
|
|
|
// When: we set a new status
|
|
asof := time.Date(2024, 1, 10, 8, 0o0, 1, 1, time.UTC)
|
|
uut.setStatus(&wgengine.Status{
|
|
LocalAddrs: []tailcfg.Endpoint{
|
|
{Addr: netip.MustParseAddrPort("[fe80::1]:5678")},
|
|
},
|
|
AsOf: asof,
|
|
}, nil)
|
|
|
|
// Then: we receive an update with the endpoint
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Equal(t, []string{"[fe80::1]:5678"}, node.Endpoints)
|
|
|
|
// Then: we store the AsOf time as lastStatus
|
|
uut.L.Lock()
|
|
require.Equal(t, uut.lastStatus, asof)
|
|
uut.L.Unlock()
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setStatus_same(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change &&
|
|
// endpoints set to {"[fe80::1]:5678"}
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.endpoints = []string{"[fe80::1]:5678"}
|
|
uut.L.Unlock()
|
|
|
|
// When: we set a status with endpoints {[fe80::1]:5678}
|
|
uut.setStatus(&wgengine.Status{LocalAddrs: []tailcfg.Endpoint{
|
|
{Addr: netip.MustParseAddrPort("[fe80::1]:5678")},
|
|
}}, nil)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setStatus_error(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change && empty endpoints
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.L.Unlock()
|
|
|
|
// When: we set a status with endpoints {[fe80::1]:5678}, with an error
|
|
uut.setStatus(&wgengine.Status{LocalAddrs: []tailcfg.Endpoint{
|
|
{Addr: netip.MustParseAddrPort("[fe80::1]:5678")},
|
|
}}, xerrors.New("test"))
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setStatus_outdated(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change && lastStatus set ahead
|
|
ahead := time.Date(2024, 1, 10, 8, 0o0, 1, 0, time.UTC)
|
|
behind := time.Date(2024, 1, 10, 8, 0o0, 0, 0, time.UTC)
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.lastStatus = ahead
|
|
uut.L.Unlock()
|
|
|
|
// When: we set a status with endpoints {[fe80::1]:5678}, with AsOf set behind
|
|
uut.setStatus(&wgengine.Status{
|
|
LocalAddrs: []tailcfg.Endpoint{{Addr: netip.MustParseAddrPort("[fe80::1]:5678")}},
|
|
AsOf: behind,
|
|
}, xerrors.New("test"))
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setAddresses_different(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Given: preferred DERP is 1, so we'll send an update
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.L.Unlock()
|
|
|
|
// When: we set addresses
|
|
addrs := []netip.Prefix{netip.MustParsePrefix("192.168.0.200/32")}
|
|
uut.setAddresses(addrs)
|
|
|
|
// Then: we receive an update with the addresses
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Equal(t, addrs, node.Addresses)
|
|
require.Equal(t, addrs, node.AllowedIPs)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setAddresses_same(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change &&
|
|
// addrs already set
|
|
addrs := []netip.Prefix{netip.MustParsePrefix("192.168.0.200/32")}
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.addresses = slices.Clone(addrs)
|
|
uut.L.Unlock()
|
|
|
|
// When: we set addrs
|
|
uut.setAddresses(addrs)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setCallback(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
nil,
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Given: preferred DERP is 1
|
|
addrs := []netip.Prefix{netip.MustParsePrefix("192.168.0.200/32")}
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.addresses = slices.Clone(addrs)
|
|
uut.L.Unlock()
|
|
|
|
// When: we set callback
|
|
nodeCh := make(chan *Node)
|
|
uut.setCallback(func(n *Node) {
|
|
nodeCh <- n
|
|
})
|
|
|
|
// Then: we get a node update
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Equal(t, 1, node.PreferredDERP)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setBlockEndpoints_different(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Given: preferred DERP is 1, so we'll send an update && some endpoints
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.endpoints = []string{"10.11.12.13:7890"}
|
|
uut.L.Unlock()
|
|
|
|
// When: we setBlockEndpoints
|
|
uut.setBlockEndpoints(true)
|
|
|
|
// Then: we receive an update without endpoints
|
|
node := testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Len(t, node.Endpoints, 0)
|
|
|
|
// When: we unset BlockEndpoints
|
|
uut.setBlockEndpoints(false)
|
|
|
|
// Then: we receive an update with endpoints
|
|
node = testutil.RequireRecvCtx(ctx, t, nodeCh)
|
|
require.Equal(t, nodeKey, node.Key)
|
|
require.Equal(t, discoKey, node.DiscoKey)
|
|
require.Len(t, node.Endpoints, 1)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_setBlockEndpoints_same(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
nodeCh := make(chan *Node)
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {
|
|
nodeCh <- n
|
|
},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// Then: we don't configure
|
|
requireNeverConfigures(ctx, t, &uut.phased)
|
|
|
|
// Given: preferred DERP is 1, so we would send an update on change &&
|
|
// blockEndpoints already set
|
|
uut.L.Lock()
|
|
uut.preferredDERP = 1
|
|
uut.blockEndpoints = true
|
|
uut.L.Unlock()
|
|
|
|
// When: we set block endpoints
|
|
uut.setBlockEndpoints(true)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_fillPeerDiagnostics(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
func(n *Node) {},
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// at start of day, filling diagnostics will not have derp and sentNode is false
|
|
d := PeerDiagnostics{}
|
|
uut.fillPeerDiagnostics(&d)
|
|
require.Equal(t, 0, d.PreferredDERP)
|
|
require.False(t, d.SentNode)
|
|
|
|
dl := map[string]float64{"1": 0.025}
|
|
uut.setNetInfo(&tailcfg.NetInfo{
|
|
PreferredDERP: 1,
|
|
DERPLatency: dl,
|
|
})
|
|
|
|
// after node callback, we should get the derp and SentNode is true.
|
|
// Use eventually since, there is a race between the callback completing
|
|
// and the test checking
|
|
require.Eventually(t, func() bool {
|
|
d := PeerDiagnostics{}
|
|
uut.fillPeerDiagnostics(&d)
|
|
// preferred DERP should be set right away, even if the callback is not
|
|
// complete.
|
|
if !assert.Equal(t, 1, d.PreferredDERP) {
|
|
return false
|
|
}
|
|
return d.SentNode
|
|
}, testutil.WaitShort, testutil.IntervalFast)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|
|
|
|
func TestNodeUpdater_fillPeerDiagnostics_noCallback(t *testing.T) {
|
|
t.Parallel()
|
|
ctx := testutil.Context(t, testutil.WaitShort)
|
|
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
|
|
id := tailcfg.NodeID(1)
|
|
nodeKey := key.NewNode().Public()
|
|
discoKey := key.NewDisco().Public()
|
|
uut := newNodeUpdater(
|
|
logger,
|
|
nil,
|
|
id, nodeKey, discoKey,
|
|
)
|
|
defer uut.close()
|
|
|
|
// at start of day, filling diagnostics will not have derp and sentNode is false
|
|
d := PeerDiagnostics{}
|
|
uut.fillPeerDiagnostics(&d)
|
|
require.Equal(t, 0, d.PreferredDERP)
|
|
require.False(t, d.SentNode)
|
|
|
|
dl := map[string]float64{"1": 0.025}
|
|
uut.setNetInfo(&tailcfg.NetInfo{
|
|
PreferredDERP: 1,
|
|
DERPLatency: dl,
|
|
})
|
|
|
|
// since there is no callback, SentNode should not be true, but we get
|
|
// the preferred DERP
|
|
uut.fillPeerDiagnostics(&d)
|
|
require.Equal(t, 1, d.PreferredDERP)
|
|
require.False(t, d.SentNode)
|
|
|
|
done := make(chan struct{})
|
|
go func() {
|
|
defer close(done)
|
|
uut.close()
|
|
}()
|
|
_ = testutil.RequireRecvCtx(ctx, t, done)
|
|
}
|