mirror of
https://github.com/slackhq/nebula.git
synced 2026-06-30 18:40:29 +02:00
98 lines
3.4 KiB
Go
98 lines
3.4 KiB
Go
package nebula
|
|
|
|
import (
|
|
"bytes"
|
|
"log/slog"
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/gaissmai/bart"
|
|
"github.com/slackhq/nebula/test"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// TestStartRelaysLogDedupe verifies that repeated attempts with the same relay set drop the log
|
|
// chatter to Debug, mirroring how the normal handshake retry loop quiets down once it's already
|
|
// announced its targets.
|
|
func TestStartRelaysLogDedupe(t *testing.T) {
|
|
vpnIp := netip.MustParseAddr("100.64.99.4")
|
|
otherRelay := netip.MustParseAddr("100.64.99.5")
|
|
|
|
newHH := func() *HandshakeHostInfo {
|
|
// Use the target's own vpnIp as the "relay" so the loop body skips it without
|
|
// touching any sender-side state. That isolates the test to the level-selection
|
|
// behavior of the top-level "Attempt to relay through hosts" log.
|
|
hostinfo := &HostInfo{
|
|
vpnAddrs: []netip.Addr{vpnIp},
|
|
localIndexId: 1,
|
|
remotes: NewRemoteList([]netip.Addr{vpnIp}, nil),
|
|
}
|
|
hostinfo.remotes.relays = []netip.Addr{vpnIp}
|
|
return &HandshakeHostInfo{hostinfo: hostinfo}
|
|
}
|
|
|
|
// Park any extra relay addresses we'll introduce mid-test in myVpnAddrsTable so the loop
|
|
// body always skips before touching f.Handshake (which would need a real handshakeManager).
|
|
addrTable := new(bart.Lite)
|
|
addrTable.Insert(netip.PrefixFrom(otherRelay, otherRelay.BitLen()))
|
|
f := &Interface{myVpnAddrsTable: addrTable}
|
|
|
|
newRM := func(buf *bytes.Buffer) *relayManager {
|
|
l := test.NewLoggerWithOutputAndLevel(buf, slog.LevelDebug)
|
|
rm := &relayManager{l: l, hostmap: newHostMap(l)}
|
|
rm.useRelays.Store(true)
|
|
return rm
|
|
}
|
|
|
|
const msg = `msg="Attempt to relay through hosts"`
|
|
|
|
t.Run("first attempt logs at Info", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
rm := newRM(&buf)
|
|
hh := newHH()
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
assert.Equal(t, []netip.Addr{vpnIp}, hh.lastRelays, "lastRelays should record the relay set we just attempted")
|
|
assert.Contains(t, buf.String(), "level=INFO "+msg, "expected Info level on first attempt")
|
|
})
|
|
|
|
t.Run("repeat attempt with same relays drops to Debug", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
rm := newRM(&buf)
|
|
hh := newHH()
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
first := append([]netip.Addr(nil), hh.lastRelays...)
|
|
buf.Reset()
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
assert.Equal(t, first, hh.lastRelays)
|
|
assert.Contains(t, buf.String(), "level=DEBUG "+msg, "expected Debug level on identical retry")
|
|
assert.NotContains(t, buf.String(), "level=INFO "+msg, "Info should not fire on identical retry")
|
|
})
|
|
|
|
t.Run("changed relay list bumps back to Info", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
rm := newRM(&buf)
|
|
hh := newHH()
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
buf.Reset()
|
|
|
|
// The lighthouse handed us a new set this round.
|
|
hh.hostinfo.remotes.relays = []netip.Addr{vpnIp, otherRelay}
|
|
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
assert.Equal(t, []netip.Addr{vpnIp, otherRelay}, hh.lastRelays)
|
|
assert.Contains(t, buf.String(), "level=INFO "+msg, "expected Info when the relay list changes")
|
|
})
|
|
|
|
t.Run("disabled relays clears lastRelays and emits no Attempt log", func(t *testing.T) {
|
|
var buf bytes.Buffer
|
|
rm := newRM(&buf)
|
|
rm.useRelays.Store(false)
|
|
hh := newHH()
|
|
hh.lastRelays = []netip.Addr{vpnIp}
|
|
|
|
rm.StartRelays(f, vpnIp, hh, nil)
|
|
assert.Nil(t, hh.lastRelays, "with relays disabled lastRelays should be cleared")
|
|
assert.NotContains(t, buf.String(), msg, "should not log when we shortcut out")
|
|
})
|
|
}
|