test: cover IPMI, PSU, and SAT formatting
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"bee/audit/internal/schema"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseIPMISELOutput(t *testing.T) {
|
||||
entries := parseIPMISELOutput(`
|
||||
1 | 06/18/2026 | 14:23:45 | Temperature #0x30 | Upper Critical going high | Asserted
|
||||
2 | 06/18/2026 | 14:24:45 | Voltage #0x21 | Upper Non-critical going high | Deasserted
|
||||
malformed
|
||||
`)
|
||||
if len(entries) != 2 {
|
||||
t.Fatalf("entries = %d, want 2", len(entries))
|
||||
}
|
||||
|
||||
first := entries[0]
|
||||
if first.Source != "ipmi-sel" || first.MessageID == nil || *first.MessageID != "1" {
|
||||
t.Fatalf("first entry identity = %#v", first)
|
||||
}
|
||||
if first.EventTime == nil || *first.EventTime != "06/18/2026 14:23:45" {
|
||||
t.Fatalf("first event time = %v", first.EventTime)
|
||||
}
|
||||
if first.ComponentRef == nil || *first.ComponentRef != "Temperature #0x30" {
|
||||
t.Fatalf("first component = %v", first.ComponentRef)
|
||||
}
|
||||
if first.Severity == nil || *first.Severity != statusCritical || first.IsActive == nil || !*first.IsActive {
|
||||
t.Fatalf("first severity/activity = %#v", first)
|
||||
}
|
||||
|
||||
second := entries[1]
|
||||
if second.Message != "Upper Non-critical going high (Deasserted)" {
|
||||
t.Fatalf("second message = %q", second.Message)
|
||||
}
|
||||
if second.Severity == nil || *second.Severity != statusWarning || second.IsActive == nil || *second.IsActive {
|
||||
t.Fatalf("second severity/activity = %#v", second)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIPMISELSeverity(t *testing.T) {
|
||||
tests := []struct {
|
||||
event string
|
||||
want string
|
||||
}{
|
||||
{event: "Upper Critical going high", want: statusCritical},
|
||||
{event: "Non-recoverable fault", want: statusCritical},
|
||||
{event: "Upper Non-critical going high", want: statusWarning},
|
||||
{event: "Voltage degraded", want: statusWarning},
|
||||
{event: "Device inserted", want: "info"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if got := ipmiSELSeverity(tt.event); got != tt.want {
|
||||
t.Errorf("ipmiSELSeverity(%q) = %q, want %q", tt.event, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIPMISensorOutput(t *testing.T) {
|
||||
sensors := parseIPMISensorOutput(`
|
||||
FAN1 | 4200 | RPM | ok | na | na | na | na | na | na
|
||||
CPU Temp | 92.5 | degrees C | ns | na | na | na | 80 | 90 | na
|
||||
CPU Temp | 80 | degrees C | ok | na | na | na | 80 | 90 | na
|
||||
PSU Input | 12.1 | Volts | ok | na | na | na | na | na | na
|
||||
System Power | 650 | Watts | cr | na | na | na | na | na | na
|
||||
Ambient | 44 | percent | nc | na | na | na | na | na | na
|
||||
Missing | na | RPM | ok
|
||||
Broken | not-a-number | RPM | ok
|
||||
`)
|
||||
if sensors == nil {
|
||||
t.Fatal("expected sensors")
|
||||
}
|
||||
if len(sensors.Fans) != 1 || sensors.Fans[0].RPM == nil || *sensors.Fans[0].RPM != 4200 {
|
||||
t.Fatalf("fans = %#v", sensors.Fans)
|
||||
}
|
||||
if len(sensors.Temperatures) != 1 {
|
||||
t.Fatalf("temperatures = %#v", sensors.Temperatures)
|
||||
}
|
||||
temp := sensors.Temperatures[0]
|
||||
if temp.ThresholdWarningCelsius == nil || *temp.ThresholdWarningCelsius != 80 ||
|
||||
temp.ThresholdCriticalCelsius == nil || *temp.ThresholdCriticalCelsius != 90 ||
|
||||
temp.Status == nil || *temp.Status != statusCritical {
|
||||
t.Fatalf("temperature = %#v", temp)
|
||||
}
|
||||
if len(sensors.Power) != 2 || sensors.Power[0].VoltageV == nil || sensors.Power[1].PowerW == nil ||
|
||||
sensors.Power[1].Status == nil || *sensors.Power[1].Status != statusCritical {
|
||||
t.Fatalf("power = %#v", sensors.Power)
|
||||
}
|
||||
if len(sensors.Other) != 1 || sensors.Other[0].Unit == nil || *sensors.Other[0].Unit != "percent" ||
|
||||
sensors.Other[0].Status == nil || *sensors.Other[0].Status != statusWarning {
|
||||
t.Fatalf("other = %#v", sensors.Other)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseIPMIThresholdAndStatus(t *testing.T) {
|
||||
if got := parseIPMIThreshold(" 42.5 "); got == nil || *got != 42.5 {
|
||||
t.Fatalf("threshold = %v, want 42.5", got)
|
||||
}
|
||||
for _, raw := range []string{"", "na", "N/A", "not-a-number"} {
|
||||
if got := parseIPMIThreshold(raw); got != nil {
|
||||
t.Errorf("parseIPMIThreshold(%q) = %v, want nil", raw, got)
|
||||
}
|
||||
}
|
||||
for raw, want := range map[string]string{
|
||||
"ok": statusOK, "cr": statusCritical, "unc": statusWarning, "na": "", "other": "",
|
||||
} {
|
||||
if got := normalizeIPMISensorStatus(raw); got != want {
|
||||
t.Errorf("normalizeIPMISensorStatus(%q) = %q, want %q", raw, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeIPMISensors(t *testing.T) {
|
||||
existing := &schema.HardwareSensors{
|
||||
Fans: []schema.HardwareFanSensor{{Name: "FAN1"}},
|
||||
}
|
||||
ipmi := &schema.HardwareSensors{
|
||||
Fans: []schema.HardwareFanSensor{{Name: "FAN1"}, {Name: "FAN2"}},
|
||||
Temperatures: []schema.HardwareTemperatureSensor{{Name: "CPU Temp"}},
|
||||
}
|
||||
merged := mergeIPMISensors(existing, ipmi)
|
||||
if merged != existing || len(merged.Fans) != 2 || len(merged.Temperatures) != 1 {
|
||||
t.Fatalf("merged = %#v", merged)
|
||||
}
|
||||
if got := mergeIPMISensors(existing, nil); got != existing {
|
||||
t.Fatal("nil IPMI sensors should preserve existing sensors")
|
||||
}
|
||||
if got := mergeIPMISensors(nil, ipmi); got != ipmi {
|
||||
t.Fatal("nil existing sensors should return IPMI sensors")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user