mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
245 lines
6.4 KiB
Go
245 lines
6.4 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/netbirdio/netbird/management/internals/controllers/network_map"
|
|
"github.com/netbirdio/netbird/management/server/mock_server"
|
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
|
)
|
|
|
|
func TestComputeForwarderPort(t *testing.T) {
|
|
// Test with empty peers list
|
|
peers := []*nbpeer.Peer{}
|
|
result := computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for empty peers list, got %d", network_map.OldForwarderPort, result)
|
|
}
|
|
|
|
// Test with peers that have old versions
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.57.0",
|
|
},
|
|
},
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.26.0",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for peers with old versions, got %d", network_map.OldForwarderPort, result)
|
|
}
|
|
|
|
// Test with peers that have new versions
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.59.0",
|
|
},
|
|
},
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.59.0",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.DnsForwarderPort) {
|
|
t.Errorf("Expected %d for peers with new versions, got %d", network_map.DnsForwarderPort, result)
|
|
}
|
|
|
|
// Test with peers that have mixed versions
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.59.0",
|
|
},
|
|
},
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "0.57.0",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for peers with mixed versions, got %d", network_map.OldForwarderPort, result)
|
|
}
|
|
|
|
// Test with peers that have empty version
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for peers with empty version, got %d", network_map.OldForwarderPort, result)
|
|
}
|
|
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "development",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result == int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for peers with dev version, got %d", network_map.DnsForwarderPort, result)
|
|
}
|
|
|
|
// Test with peers that have unknown version string
|
|
peers = []*nbpeer.Peer{
|
|
{
|
|
Meta: nbpeer.PeerSystemMeta{
|
|
WtVersion: "unknown",
|
|
},
|
|
},
|
|
}
|
|
result = computeForwarderPort(peers, "v0.59.0")
|
|
if result != int64(network_map.OldForwarderPort) {
|
|
t.Errorf("Expected %d for peers with unknown version, got %d", network_map.OldForwarderPort, result)
|
|
}
|
|
}
|
|
|
|
func TestBufferUpdateAccountPeers(t *testing.T) {
|
|
const (
|
|
peersCount = 1000
|
|
updateAccountInterval = 50 * time.Millisecond
|
|
)
|
|
|
|
var (
|
|
deletedPeers, updatePeersDeleted, updatePeersRuns atomic.Int32
|
|
uapLastRun, dpLastRun atomic.Int64
|
|
|
|
totalNewRuns, totalOldRuns int
|
|
)
|
|
|
|
uap := func(ctx context.Context, accountID string) {
|
|
updatePeersDeleted.Store(deletedPeers.Load())
|
|
updatePeersRuns.Add(1)
|
|
uapLastRun.Store(time.Now().UnixMilli())
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
|
|
t.Run("new approach", func(t *testing.T) {
|
|
updatePeersRuns.Store(0)
|
|
updatePeersDeleted.Store(0)
|
|
deletedPeers.Store(0)
|
|
|
|
var mustore sync.Map
|
|
bufupd := func(ctx context.Context, accountID string) {
|
|
mu, _ := mustore.LoadOrStore(accountID, &bufferUpdate{})
|
|
b := mu.(*bufferUpdate)
|
|
|
|
if !b.mu.TryLock() {
|
|
b.update.Store(true)
|
|
return
|
|
}
|
|
|
|
if b.next != nil {
|
|
b.next.Stop()
|
|
}
|
|
|
|
go func() {
|
|
defer b.mu.Unlock()
|
|
uap(ctx, accountID)
|
|
if !b.update.Load() {
|
|
return
|
|
}
|
|
b.update.Store(false)
|
|
b.next = time.AfterFunc(updateAccountInterval, func() {
|
|
uap(ctx, accountID)
|
|
})
|
|
}()
|
|
}
|
|
dp := func(ctx context.Context, accountID, peerID, userID string) error {
|
|
deletedPeers.Add(1)
|
|
dpLastRun.Store(time.Now().UnixMilli())
|
|
time.Sleep(10 * time.Millisecond)
|
|
bufupd(ctx, accountID)
|
|
return nil
|
|
}
|
|
|
|
am := mock_server.MockAccountManager{
|
|
UpdateAccountPeersFunc: uap,
|
|
BufferUpdateAccountPeersFunc: bufupd,
|
|
DeletePeerFunc: dp,
|
|
}
|
|
empty := ""
|
|
for range peersCount {
|
|
//nolint
|
|
am.DeletePeer(context.Background(), empty, empty, empty)
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
assert.Equal(t, peersCount, int(deletedPeers.Load()), "Expected all peers to be deleted")
|
|
assert.Equal(t, peersCount, int(updatePeersDeleted.Load()), "Expected all peers to be updated in the buffer")
|
|
assert.GreaterOrEqual(t, uapLastRun.Load(), dpLastRun.Load(), "Expected update account peers to run after delete peer")
|
|
|
|
totalNewRuns = int(updatePeersRuns.Load())
|
|
})
|
|
|
|
t.Run("old approach", func(t *testing.T) {
|
|
updatePeersRuns.Store(0)
|
|
updatePeersDeleted.Store(0)
|
|
deletedPeers.Store(0)
|
|
|
|
var mustore sync.Map
|
|
bufupd := func(ctx context.Context, accountID string) {
|
|
mu, _ := mustore.LoadOrStore(accountID, &sync.Mutex{})
|
|
b := mu.(*sync.Mutex)
|
|
|
|
if !b.TryLock() {
|
|
return
|
|
}
|
|
|
|
go func() {
|
|
time.Sleep(updateAccountInterval)
|
|
b.Unlock()
|
|
uap(ctx, accountID)
|
|
}()
|
|
}
|
|
dp := func(ctx context.Context, accountID, peerID, userID string) error {
|
|
deletedPeers.Add(1)
|
|
dpLastRun.Store(time.Now().UnixMilli())
|
|
time.Sleep(10 * time.Millisecond)
|
|
bufupd(ctx, accountID)
|
|
return nil
|
|
}
|
|
|
|
am := mock_server.MockAccountManager{
|
|
UpdateAccountPeersFunc: uap,
|
|
BufferUpdateAccountPeersFunc: bufupd,
|
|
DeletePeerFunc: dp,
|
|
}
|
|
empty := ""
|
|
for range peersCount {
|
|
//nolint
|
|
am.DeletePeer(context.Background(), empty, empty, empty)
|
|
}
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
assert.Equal(t, peersCount, int(deletedPeers.Load()), "Expected all peers to be deleted")
|
|
assert.Equal(t, peersCount, int(updatePeersDeleted.Load()), "Expected all peers to be updated in the buffer")
|
|
assert.GreaterOrEqual(t, uapLastRun.Load(), dpLastRun.Load(), "Expected update account peers to run after delete peer")
|
|
|
|
totalOldRuns = int(updatePeersRuns.Load())
|
|
})
|
|
assert.Less(t, totalNewRuns, totalOldRuns, "Expected new approach to run less than old approach. New runs: %d, Old runs: %d", totalNewRuns, totalOldRuns)
|
|
t.Logf("New runs: %d, Old runs: %d", totalNewRuns, totalOldRuns)
|
|
}
|