Add tests
This commit is contained in:
250
src/vpp/vpp_stats_test.go
Normal file
250
src/vpp/vpp_stats_test.go
Normal file
@@ -0,0 +1,250 @@
|
||||
// Copyright 2025, IPng Networks GmbH, Pim van Pelt <pim@ipng.ch>
|
||||
|
||||
package vpp
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go.fd.io/govpp/api"
|
||||
)
|
||||
|
||||
func TestNewStatsManager(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
if manager == nil {
|
||||
t.Fatal("NewStatsManager() returned nil")
|
||||
}
|
||||
|
||||
if manager.client != client {
|
||||
t.Error("StatsManager should store the provided client")
|
||||
}
|
||||
|
||||
if manager.interfaceManager != interfaceManager {
|
||||
t.Error("StatsManager should store the provided interface manager")
|
||||
}
|
||||
|
||||
if manager.period != time.Duration(*Period)*time.Second {
|
||||
t.Errorf("Expected period %v, got %v", time.Duration(*Period)*time.Second, manager.period)
|
||||
}
|
||||
|
||||
if manager.running {
|
||||
t.Error("StatsManager should not be running initially")
|
||||
}
|
||||
|
||||
if manager.statsCallback != nil {
|
||||
t.Error("StatsManager should have nil callback initially")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerSetStatsCallback(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
var callbackCalled bool
|
||||
var receivedStats *api.InterfaceStats
|
||||
|
||||
callback := func(stats *api.InterfaceStats) {
|
||||
callbackCalled = true
|
||||
receivedStats = stats
|
||||
}
|
||||
|
||||
manager.SetStatsCallback(callback)
|
||||
|
||||
if manager.statsCallback == nil {
|
||||
t.Error("SetStatsCallback() should store the callback")
|
||||
}
|
||||
|
||||
// Test callback execution
|
||||
testStats := &api.InterfaceStats{
|
||||
Interfaces: []api.InterfaceCounters{
|
||||
{
|
||||
InterfaceIndex: 1,
|
||||
InterfaceName: "test-interface",
|
||||
Rx: api.InterfaceCounterCombined{Packets: 100, Bytes: 1500},
|
||||
Tx: api.InterfaceCounterCombined{Packets: 50, Bytes: 750},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
manager.statsCallback(testStats)
|
||||
|
||||
if !callbackCalled {
|
||||
t.Error("Callback should have been called")
|
||||
}
|
||||
|
||||
if receivedStats != testStats {
|
||||
t.Error("Callback should receive the same stats object")
|
||||
}
|
||||
|
||||
if len(receivedStats.Interfaces) != 1 {
|
||||
t.Errorf("Expected 1 interface, got %d", len(receivedStats.Interfaces))
|
||||
}
|
||||
|
||||
if receivedStats.Interfaces[0].InterfaceName != "test-interface" {
|
||||
t.Errorf("Expected interface name 'test-interface', got %q", receivedStats.Interfaces[0].InterfaceName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerSetPeriod(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
newPeriod := 5 * time.Second
|
||||
manager.SetPeriod(newPeriod)
|
||||
|
||||
if manager.period != newPeriod {
|
||||
t.Errorf("Expected period %v, got %v", newPeriod, manager.period)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerStartStopStatsRoutine(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
if manager.running {
|
||||
t.Error("StatsManager should not be running initially")
|
||||
}
|
||||
|
||||
manager.StartStatsRoutine()
|
||||
|
||||
if !manager.running {
|
||||
t.Error("StatsManager should be running after StartStatsRoutine()")
|
||||
}
|
||||
|
||||
// Test starting again (should be safe)
|
||||
manager.StartStatsRoutine()
|
||||
|
||||
if !manager.running {
|
||||
t.Error("StatsManager should still be running after second StartStatsRoutine()")
|
||||
}
|
||||
|
||||
manager.StopStatsRoutine()
|
||||
|
||||
if manager.running {
|
||||
t.Error("StatsManager should not be running after StopStatsRoutine()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerGetInterfaceStatsWithoutConnection(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
_, err := manager.GetInterfaceStats()
|
||||
if err == nil {
|
||||
t.Error("GetInterfaceStats() should return error when not connected")
|
||||
}
|
||||
|
||||
vppErr, ok := err.(*VPPError)
|
||||
if !ok {
|
||||
t.Errorf("Expected VPPError, got %T", err)
|
||||
}
|
||||
|
||||
if vppErr.Message != "VPP client not connected" {
|
||||
t.Errorf("Expected specific error message, got: %s", vppErr.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsCallback(t *testing.T) {
|
||||
var callbackInvoked bool
|
||||
var callbackStats *api.InterfaceStats
|
||||
|
||||
callback := StatsCallback(func(stats *api.InterfaceStats) {
|
||||
callbackInvoked = true
|
||||
callbackStats = stats
|
||||
})
|
||||
|
||||
testStats := &api.InterfaceStats{
|
||||
Interfaces: []api.InterfaceCounters{
|
||||
{
|
||||
InterfaceIndex: 42,
|
||||
InterfaceName: "test-callback-interface",
|
||||
Rx: api.InterfaceCounterCombined{Packets: 200, Bytes: 3000},
|
||||
Tx: api.InterfaceCounterCombined{Packets: 100, Bytes: 1500},
|
||||
RxUnicast: api.InterfaceCounterCombined{Packets: 180, Bytes: 2700},
|
||||
TxUnicast: api.InterfaceCounterCombined{Packets: 90, Bytes: 1350},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
callback(testStats)
|
||||
|
||||
if !callbackInvoked {
|
||||
t.Error("Callback should have been invoked")
|
||||
}
|
||||
|
||||
if callbackStats != testStats {
|
||||
t.Error("Callback should receive the same stats object")
|
||||
}
|
||||
|
||||
if len(callbackStats.Interfaces) != 1 {
|
||||
t.Errorf("Expected 1 interface, got %d", len(callbackStats.Interfaces))
|
||||
}
|
||||
|
||||
iface := callbackStats.Interfaces[0]
|
||||
if iface.InterfaceIndex != 42 {
|
||||
t.Errorf("Expected interface index 42, got %d", iface.InterfaceIndex)
|
||||
}
|
||||
|
||||
if iface.InterfaceName != "test-callback-interface" {
|
||||
t.Errorf("Expected interface name 'test-callback-interface', got %q", iface.InterfaceName)
|
||||
}
|
||||
|
||||
if iface.Rx.Packets != 200 {
|
||||
t.Errorf("Expected RX packets 200, got %d", iface.Rx.Packets)
|
||||
}
|
||||
|
||||
if iface.Tx.Bytes != 1500 {
|
||||
t.Errorf("Expected TX bytes 1500, got %d", iface.Tx.Bytes)
|
||||
}
|
||||
|
||||
if iface.RxUnicast.Packets != 180 {
|
||||
t.Errorf("Expected RX unicast packets 180, got %d", iface.RxUnicast.Packets)
|
||||
}
|
||||
|
||||
if iface.TxUnicast.Bytes != 1350 {
|
||||
t.Errorf("Expected TX unicast bytes 1350, got %d", iface.TxUnicast.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerQueryAndReportStatsWithoutConnection(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
// Should return false when not connected
|
||||
if manager.queryAndReportStats() {
|
||||
t.Error("queryAndReportStats() should return false when not connected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatsManagerWithShortPeriod(t *testing.T) {
|
||||
client := NewVPPClient()
|
||||
interfaceManager := NewInterfaceManager(client)
|
||||
manager := NewStatsManager(client, interfaceManager)
|
||||
|
||||
// Set a very short period for testing
|
||||
manager.SetPeriod(10 * time.Millisecond)
|
||||
|
||||
if manager.period != 10*time.Millisecond {
|
||||
t.Errorf("Expected period 10ms, got %v", manager.period)
|
||||
}
|
||||
|
||||
manager.StartStatsRoutine()
|
||||
|
||||
// Let it run briefly
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
manager.StopStatsRoutine()
|
||||
|
||||
// Should stop gracefully
|
||||
if manager.running {
|
||||
t.Error("StatsManager should have stopped")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user