Files
Pulse/pkg/agents/host/report_test.go
2025-11-26 14:16:57 +00:00

392 lines
9.5 KiB
Go

package host
import (
"encoding/json"
"testing"
"time"
)
func TestReport_JSONMarshal(t *testing.T) {
report := Report{
Agent: AgentInfo{
ID: "agent-1",
Version: "1.0.0",
Type: "unified",
IntervalSeconds: 30,
Hostname: "myhost",
},
Host: HostInfo{
ID: "host-1",
Hostname: "myhost",
DisplayName: "My Host",
Platform: "linux",
CPUCount: 4,
UptimeSeconds: 86400,
LoadAverage: []float64{0.5, 0.7, 0.9},
},
Metrics: Metrics{
CPUUsagePercent: 25.5,
Memory: MemoryMetric{
TotalBytes: 16000000000,
UsedBytes: 8000000000,
FreeBytes: 8000000000,
Usage: 50.0,
},
},
Timestamp: time.Now(),
}
data, err := json.Marshal(report)
if err != nil {
t.Fatalf("Failed to marshal Report: %v", err)
}
var decoded Report
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("Failed to unmarshal Report: %v", err)
}
if decoded.Agent.ID != report.Agent.ID {
t.Errorf("Agent.ID = %q, want %q", decoded.Agent.ID, report.Agent.ID)
}
if decoded.Host.Hostname != report.Host.Hostname {
t.Errorf("Host.Hostname = %q, want %q", decoded.Host.Hostname, report.Host.Hostname)
}
if decoded.Metrics.CPUUsagePercent != report.Metrics.CPUUsagePercent {
t.Errorf("Metrics.CPUUsagePercent = %f, want %f", decoded.Metrics.CPUUsagePercent, report.Metrics.CPUUsagePercent)
}
}
func TestAgentInfo_Fields(t *testing.T) {
agent := AgentInfo{
ID: "agent-123",
Version: "2.0.0",
Type: "host",
IntervalSeconds: 60,
Hostname: "server1",
}
if agent.ID != "agent-123" {
t.Errorf("ID = %q, want agent-123", agent.ID)
}
if agent.Version != "2.0.0" {
t.Errorf("Version = %q, want 2.0.0", agent.Version)
}
if agent.Type != "host" {
t.Errorf("Type = %q, want host", agent.Type)
}
if agent.IntervalSeconds != 60 {
t.Errorf("IntervalSeconds = %d, want 60", agent.IntervalSeconds)
}
if agent.Hostname != "server1" {
t.Errorf("Hostname = %q, want server1", agent.Hostname)
}
}
func TestHostInfo_Fields(t *testing.T) {
host := HostInfo{
ID: "host-456",
Hostname: "myserver",
DisplayName: "My Server",
MachineID: "abc123",
Platform: "linux",
OSName: "Ubuntu",
OSVersion: "22.04",
KernelVersion: "5.15.0",
Architecture: "x86_64",
CPUModel: "Intel Core i7",
CPUCount: 8,
UptimeSeconds: 172800,
LoadAverage: []float64{1.0, 0.8, 0.6},
}
if host.ID != "host-456" {
t.Errorf("ID = %q, want host-456", host.ID)
}
if host.Platform != "linux" {
t.Errorf("Platform = %q, want linux", host.Platform)
}
if host.CPUCount != 8 {
t.Errorf("CPUCount = %d, want 8", host.CPUCount)
}
if len(host.LoadAverage) != 3 {
t.Errorf("LoadAverage length = %d, want 3", len(host.LoadAverage))
}
}
func TestMemoryMetric_Fields(t *testing.T) {
mem := MemoryMetric{
TotalBytes: 32000000000,
UsedBytes: 16000000000,
FreeBytes: 16000000000,
Usage: 50.0,
SwapTotal: 8000000000,
SwapUsed: 2000000000,
}
if mem.TotalBytes != 32000000000 {
t.Errorf("TotalBytes = %d, want 32000000000", mem.TotalBytes)
}
if mem.Usage != 50.0 {
t.Errorf("Usage = %f, want 50.0", mem.Usage)
}
if mem.SwapTotal != 8000000000 {
t.Errorf("SwapTotal = %d, want 8000000000", mem.SwapTotal)
}
}
func TestDisk_Fields(t *testing.T) {
disk := Disk{
Device: "/dev/sda1",
Mountpoint: "/",
Filesystem: "ext4",
Type: "ext4",
TotalBytes: 500000000000,
UsedBytes: 250000000000,
FreeBytes: 250000000000,
Usage: 50.0,
}
if disk.Device != "/dev/sda1" {
t.Errorf("Device = %q, want /dev/sda1", disk.Device)
}
if disk.Mountpoint != "/" {
t.Errorf("Mountpoint = %q, want /", disk.Mountpoint)
}
if disk.Usage != 50.0 {
t.Errorf("Usage = %f, want 50.0", disk.Usage)
}
}
func TestNetworkInterface_Fields(t *testing.T) {
speed := int64(1000)
net := NetworkInterface{
Name: "eth0",
MAC: "00:11:22:33:44:55",
Addresses: []string{"192.168.1.100", "fe80::1"},
RXBytes: 1000000,
TXBytes: 500000,
SpeedMbps: &speed,
}
if net.Name != "eth0" {
t.Errorf("Name = %q, want eth0", net.Name)
}
if net.MAC != "00:11:22:33:44:55" {
t.Errorf("MAC = %q, want 00:11:22:33:44:55", net.MAC)
}
if len(net.Addresses) != 2 {
t.Errorf("Addresses length = %d, want 2", len(net.Addresses))
}
if *net.SpeedMbps != 1000 {
t.Errorf("SpeedMbps = %d, want 1000", *net.SpeedMbps)
}
}
func TestSensors_Fields(t *testing.T) {
sensors := Sensors{
TemperatureCelsius: map[string]float64{
"cpu_package": 45.0,
"cpu_core_0": 43.0,
"cpu_core_1": 44.0,
},
FanRPM: map[string]float64{
"cpu_fan": 1200.0,
},
Additional: map[string]float64{
"voltage": 12.0,
},
}
if len(sensors.TemperatureCelsius) != 3 {
t.Errorf("TemperatureCelsius count = %d, want 3", len(sensors.TemperatureCelsius))
}
if sensors.TemperatureCelsius["cpu_package"] != 45.0 {
t.Errorf("cpu_package temp = %f, want 45.0", sensors.TemperatureCelsius["cpu_package"])
}
if sensors.FanRPM["cpu_fan"] != 1200.0 {
t.Errorf("cpu_fan RPM = %f, want 1200.0", sensors.FanRPM["cpu_fan"])
}
}
func TestRAIDArray_Fields(t *testing.T) {
array := RAIDArray{
Device: "/dev/md0",
Name: "myarray",
Level: "raid1",
State: "clean",
TotalDevices: 2,
ActiveDevices: 2,
WorkingDevices: 2,
FailedDevices: 0,
SpareDevices: 0,
UUID: "12345678:90abcdef:12345678:90abcdef",
RebuildPercent: 0,
RebuildSpeed: "",
Devices: []RAIDDevice{
{Device: "/dev/sda1", State: "active sync", Slot: 0},
{Device: "/dev/sdb1", State: "active sync", Slot: 1},
},
}
if array.Device != "/dev/md0" {
t.Errorf("Device = %q, want /dev/md0", array.Device)
}
if array.Level != "raid1" {
t.Errorf("Level = %q, want raid1", array.Level)
}
if array.State != "clean" {
t.Errorf("State = %q, want clean", array.State)
}
if len(array.Devices) != 2 {
t.Errorf("Devices count = %d, want 2", len(array.Devices))
}
}
func TestRAIDDevice_Fields(t *testing.T) {
device := RAIDDevice{
Device: "/dev/sda1",
State: "active sync",
Slot: 0,
}
if device.Device != "/dev/sda1" {
t.Errorf("Device = %q, want /dev/sda1", device.Device)
}
if device.State != "active sync" {
t.Errorf("State = %q, want active sync", device.State)
}
if device.Slot != 0 {
t.Errorf("Slot = %d, want 0", device.Slot)
}
}
func TestRAIDArray_Degraded(t *testing.T) {
array := RAIDArray{
Device: "/dev/md1",
Level: "raid5",
State: "clean, degraded",
TotalDevices: 3,
ActiveDevices: 2,
WorkingDevices: 2,
FailedDevices: 1,
SpareDevices: 0,
Devices: []RAIDDevice{
{Device: "/dev/sda1", State: "active sync", Slot: 0},
{Device: "/dev/sdb1", State: "faulty", Slot: -1},
{Device: "/dev/sdc1", State: "active sync", Slot: 2},
},
}
if array.FailedDevices != 1 {
t.Errorf("FailedDevices = %d, want 1", array.FailedDevices)
}
if array.State != "clean, degraded" {
t.Errorf("State = %q, want 'clean, degraded'", array.State)
}
}
func TestRAIDArray_Rebuilding(t *testing.T) {
array := RAIDArray{
Device: "/dev/md2",
Level: "raid6",
State: "active, recovering",
RebuildPercent: 42.5,
RebuildSpeed: "50000K/sec",
}
if array.RebuildPercent != 42.5 {
t.Errorf("RebuildPercent = %f, want 42.5", array.RebuildPercent)
}
if array.RebuildSpeed != "50000K/sec" {
t.Errorf("RebuildSpeed = %q, want 50000K/sec", array.RebuildSpeed)
}
}
func TestReport_WithDisksAndNetwork(t *testing.T) {
report := Report{
Disks: []Disk{
{Device: "/dev/sda1", Mountpoint: "/", TotalBytes: 500000000000},
{Device: "/dev/sdb1", Mountpoint: "/data", TotalBytes: 1000000000000},
},
Network: []NetworkInterface{
{Name: "eth0", RXBytes: 1000000, TXBytes: 500000},
{Name: "eth1", RXBytes: 2000000, TXBytes: 1000000},
},
}
if len(report.Disks) != 2 {
t.Errorf("Disks count = %d, want 2", len(report.Disks))
}
if len(report.Network) != 2 {
t.Errorf("Network count = %d, want 2", len(report.Network))
}
}
func TestReport_WithSensorsAndRAID(t *testing.T) {
report := Report{
Sensors: Sensors{
TemperatureCelsius: map[string]float64{"cpu": 45.0},
},
RAID: []RAIDArray{
{Device: "/dev/md0", Level: "raid1", State: "clean"},
},
}
if len(report.Sensors.TemperatureCelsius) != 1 {
t.Errorf("TemperatureCelsius count = %d, want 1", len(report.Sensors.TemperatureCelsius))
}
if len(report.RAID) != 1 {
t.Errorf("RAID count = %d, want 1", len(report.RAID))
}
}
func TestReport_Tags(t *testing.T) {
report := Report{
Tags: []string{"production", "web", "us-east"},
}
if len(report.Tags) != 3 {
t.Errorf("Tags count = %d, want 3", len(report.Tags))
}
if report.Tags[0] != "production" {
t.Errorf("Tags[0] = %q, want production", report.Tags[0])
}
}
func TestReport_JSONOmitEmpty(t *testing.T) {
// Test that empty fields are omitted in JSON
report := Report{
Agent: AgentInfo{ID: "agent-1"},
Host: HostInfo{Hostname: "myhost"},
}
data, err := json.Marshal(report)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
}
jsonStr := string(data)
// These should not appear in JSON when empty
if contains(jsonStr, `"disks":[]`) {
t.Error("Empty disks should be omitted")
}
if contains(jsonStr, `"network":[]`) {
t.Error("Empty network should be omitted")
}
if contains(jsonStr, `"tags":[]`) {
t.Error("Empty tags should be omitted")
}
}
// Helper function
func contains(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}