Files
pulse/internal/monitoring/monitor_libvirt_test.go
T
2026-07-30 20:22:47 +01:00

111 lines
3.6 KiB
Go

package monitoring
import (
"math"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
agentshost "github.com/rcourtman/pulse-go-rewrite/pkg/agents/host"
)
func TestNormalizeAgentLibvirtInventoryDerivesCPUAndIORates(t *testing.T) {
monitor := &Monitor{rateTracker: NewRateTracker()}
t0 := time.Date(2026, 7, 30, 12, 0, 0, 0, time.UTC)
firstReport := &agentshost.LibvirtInventory{Domains: []agentshost.LibvirtDomain{{
Name: "app",
State: "running",
VCPUs: 2,
CPUTimeNanoseconds: 2_000_000_000,
MemoryCurrentBytes: 2 << 30,
MemoryMaximumBytes: 4 << 30,
NetworkRXBytes: 1000,
NetworkTXBytes: 2000,
DiskReadBytes: 3000,
DiskWriteBytes: 4000,
}}}
first := monitor.normalizeAgentLibvirtInventory(firstReport, "host-1", nil, t0)
if first == nil || len(first.Domains) != 1 {
t.Fatalf("first inventory = %+v", first)
}
if first.Domains[0].CPUUsageValid || first.Domains[0].IORatesValid {
t.Fatalf("first sample invented rates: %+v", first.Domains[0])
}
previous := &models.Host{
ID: "host-1",
LastSeen: t0,
Libvirt: first,
}
secondReport := &agentshost.LibvirtInventory{Domains: []agentshost.LibvirtDomain{{
Name: "app",
State: "running",
VCPUs: 2,
CPUTimeNanoseconds: 3_000_000_000,
MemoryCurrentBytes: 5 << 30,
MemoryMaximumBytes: 4 << 30,
NetworkRXBytes: 2000,
NetworkTXBytes: 4000,
DiskReadBytes: 6000,
DiskWriteBytes: 8000,
}}}
second := monitor.normalizeAgentLibvirtInventory(secondReport, "host-1", previous, t0.Add(10*time.Second))
if second == nil || len(second.Domains) != 1 {
t.Fatalf("second inventory = %+v", second)
}
got := second.Domains[0]
if !got.CPUUsageValid || math.Abs(got.CPUUsagePercent-5) > 0.001 {
t.Fatalf("CPU usage = (%v, %v), want valid 5%%", got.CPUUsagePercent, got.CPUUsageValid)
}
if !got.IORatesValid ||
got.NetworkInRate != 100 ||
got.NetworkOutRate != 200 ||
got.DiskReadRate != 300 ||
got.DiskWriteRate != 400 {
t.Fatalf("I/O rates = %+v", got)
}
if got.MemoryCurrentBytes != 4<<30 {
t.Fatalf("memory current = %d, want clamped to maximum", got.MemoryCurrentBytes)
}
}
func TestNormalizeAgentLibvirtInventoryBoundsAndDeduplicates(t *testing.T) {
monitor := &Monitor{rateTracker: NewRateTracker()}
report := &agentshost.LibvirtInventory{Domains: []agentshost.LibvirtDomain{
{Name: " VM ", State: "CRASHED", VCPUs: 5000},
{Name: "vm", State: "running"},
{Name: "bad\x00name", State: "running"},
}}
got := monitor.normalizeAgentLibvirtInventory(report, "host-1", nil, time.Now())
if got == nil || len(got.Domains) != 1 {
t.Fatalf("inventory = %+v, want one domain", got)
}
if got.Domains[0].Name != "VM" || got.Domains[0].State != "crashed" || got.Domains[0].VCPUs != 4096 {
t.Fatalf("normalized domain = %+v", got.Domains[0])
}
}
func TestNormalizeAgentLibvirtInventoryPreservesLastSuccessfulSampleOnFailure(t *testing.T) {
collectedAt := time.Now().Add(-time.Minute).UTC()
previous := &models.Host{Libvirt: &models.HostLibvirtInventory{
CollectedAt: collectedAt,
Domains: []models.HostLibvirtDomain{{
ID: "domain-a",
Name: "app",
}},
}}
got := (&Monitor{rateTracker: NewRateTracker()}).normalizeAgentLibvirtInventory(
nil,
"host-1",
previous,
time.Now(),
)
if got == nil || len(got.Domains) != 1 || !got.CollectedAt.Equal(collectedAt) {
t.Fatalf("preserved inventory = %+v", got)
}
got.Domains[0].Name = "mutated"
if previous.Libvirt.Domains[0].Name != "app" {
t.Fatal("preserved inventory aliases previous host state")
}
}