From cf9c6b8909ab6b08421a0f7586206cd7d2b899ef Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Sat, 12 Sep 2026 16:42:13 +0300 Subject: [PATCH] test: make portable fixtures optional and cover xigmanas --- ...profile_inspur_group_oem_platforms_test.go | 3 + internal/parser/vendors/xigmanas/parser.go | 2 +- .../parser/vendors/xigmanas/parser_test.go | 82 +++++++++++++++++++ internal/server/chart_view_test.go | 8 +- .../reanimator_example_regression_test.go | 3 + 5 files changed, 93 insertions(+), 5 deletions(-) diff --git a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go index 70ee38c..8ddc6e5 100644 --- a/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go +++ b/internal/collector/redfishprofile/profile_inspur_group_oem_platforms_test.go @@ -186,6 +186,9 @@ func loadRawExportTreeFromExampleZip(t *testing.T, name string) map[string]inter path := filepath.Join("..", "..", "..", "example", name) f, err := os.Open(path) if err != nil { + if os.IsNotExist(err) { + t.Skipf("optional example zip %s is not present", path) + } t.Fatalf("open example zip %s: %v", path, err) } defer f.Close() diff --git a/internal/parser/vendors/xigmanas/parser.go b/internal/parser/vendors/xigmanas/parser.go index ad98dc1..5097670 100644 --- a/internal/parser/vendors/xigmanas/parser.go +++ b/internal/parser/vendors/xigmanas/parser.go @@ -238,7 +238,7 @@ func parseStorageAndSMART(content string, result *models.AnalysisResult) { storageBySlot := make(map[string]*models.Storage) scsiRe := regexp.MustCompile(`(?m)^<([^>]+)>\s+at\s+scbus\d+\s+target\s+\d+\s+lun\s+\d+\s+\(([^,]+),([^)]+)\)$`) for _, m := range scsiRe.FindAllStringSubmatch(content, -1) { - slot := strings.TrimSpace(m[3]) + slot := strings.TrimSpace(m[2]) model, fw := splitModelAndFirmware(strings.TrimSpace(m[1])) entry := &models.Storage{ Slot: slot, diff --git a/internal/parser/vendors/xigmanas/parser_test.go b/internal/parser/vendors/xigmanas/parser_test.go index d35349c..5ed3ae6 100644 --- a/internal/parser/vendors/xigmanas/parser_test.go +++ b/internal/parser/vendors/xigmanas/parser_test.go @@ -38,6 +38,88 @@ loader_brand="XigmaNAS"`), } } +func TestParserParseInlineDump(t *testing.T) { + p := &Parser{} + result, err := p.Parse([]parser.ExtractedFile{{Path: "diagnostic.txt", Content: []byte(`Version: +-------- +14.3.0.5 +smbios.bios.version="F.22" +smbios.system.maker="Acme" +smbios.system.product="NAS-1" +smbios.system.serial="SN-1" +smbios.system.uuid="uuid-1" +FreeBSD/SMP: 1 package(s) x 4 core(s) +CPU: AMD Ryzen 5 3600 (3600.00-MHz) +CPU: AMD Ryzen 5 3600 (3600.00-MHz) +real memory = 8589934592 (8192 MB) +10:10AM up 2 days, 3 users, load averages: 0.10, 0.20, 0.30 +state: DEGRADED + at scbus0 target 0 lun 0 (da0,pass0) +S.M.A.R.T. [/dev/da0]: +-------- +Device Model: WDC WD10EZEX +Serial Number: DISK-1 +Firmware Version: 1.01 +User Capacity: 1,000,000,000 bytes +SMART overall-health self-assessment test result: FAILED +194 Temperature_Celsius 0x0022 100 100 000 Old_age Always - 41 +Last 275 System log entries: +-------- +2026-01-02T03:04:05+00:00 host kernel: fatal disk error +Last 275 SMARTD log entries: +-------- +Jan 2 03:04:05 host smartd: warning temperature +Last 275 Daemon log entries: +-------- +plain informational line +`)}}) + if err != nil { + t.Fatalf("Parse: %v", err) + } + if result.Hardware.BoardInfo.ProductName != "NAS-1" || len(result.Hardware.Firmware) != 2 { + t.Fatalf("unexpected board or firmware: %+v / %+v", result.Hardware.BoardInfo, result.Hardware.Firmware) + } + if len(result.Hardware.CPUs) != 1 || result.Hardware.CPUs[0].Cores != 4 { + t.Fatalf("unexpected CPUs: %+v", result.Hardware.CPUs) + } + if len(result.Hardware.Memory) != 1 || result.Hardware.Memory[0].SizeMB != 8192 { + t.Fatalf("unexpected memory: %+v", result.Hardware.Memory) + } + if len(result.Hardware.Storage) != 1 || result.Hardware.Storage[0].SizeGB != 1 || result.Hardware.Storage[0].SerialNumber != "DISK-1" { + t.Fatalf("unexpected storage: %+v", result.Hardware.Storage) + } + if len(result.Sensors) != 1 || result.Sensors[0].Status != "warning" { + t.Fatalf("unexpected sensors: %+v", result.Sensors) + } + if len(result.Events) != 6 { + t.Fatalf("expected uptime, ZFS, SMART, and three log events, got %+v", result.Events) + } +} + +func TestXigmaNASHelpers(t *testing.T) { + if model, fw := splitModelAndFirmware("disk model 1.00"); model != "disk model" || fw != "1.00" { + t.Fatalf("splitModelAndFirmware = %q, %q", model, fw) + } + if got := guessStorageType("cd0"); got != "optical" { + t.Fatalf("optical type = %q", got) + } + if got := guessStorageType("ada0"); got != "hdd" { + t.Fatalf("HDD type = %q", got) + } + if got := parseCapacityBytes("invalid"); got != 0 { + t.Fatalf("invalid capacity = %d", got) + } + if got := classifyEventSeverity("all good"); got != "info" { + t.Fatalf("info severity = %q", got) + } + if got := classifyEventSeverity("kernel panic"); got != "critical" { + t.Fatalf("critical severity = %q", got) + } + if got := extractSyslogMessage("a: message"); got != "message" { + t.Fatalf("syslog message = %q", got) + } +} + func TestParserParseExample(t *testing.T) { p := &Parser{} diff --git a/internal/server/chart_view_test.go b/internal/server/chart_view_test.go index 5cd5067..3f10461 100644 --- a/internal/server/chart_view_test.go +++ b/internal/server/chart_view_test.go @@ -43,11 +43,11 @@ func TestHandleChartCurrent_RendersCurrentReanimatorSnapshot(t *testing.T) { if !strings.Contains(body, "SYS-TEST - SN123") { t.Fatalf("expected chart title in body, got %q", body) } - if !strings.Contains(body, `/chart/static/view.css`) { - t.Fatalf("expected rewritten chart css path, got %q", body) + if !strings.Contains(body, `static/view.css`) { + t.Fatalf("expected chart css path, got %q", body) } - if !strings.Contains(body, `/chart/static/view.js`) { - t.Fatalf("expected rewritten chart js path, got %q", body) + if !strings.Contains(body, `static/view.js`) { + t.Fatalf("expected chart js path, got %q", body) } if !strings.Contains(body, "Snapshot Metadata") { t.Fatalf("expected rendered chart output, got %q", body) diff --git a/internal/server/reanimator_example_regression_test.go b/internal/server/reanimator_example_regression_test.go index 5dcca11..f1d5f70 100644 --- a/internal/server/reanimator_example_regression_test.go +++ b/internal/server/reanimator_example_regression_test.go @@ -12,6 +12,9 @@ import ( func TestReanimatorExport_RedfishExampleDoesNotDuplicateCPUs(t *testing.T) { payload, err := os.ReadFile(filepath.Join("..", "..", "example", "2026-03-11 (SYS-821GE-TNHR) - A514359X5C08846.zip")) if err != nil { + if os.IsNotExist(err) { + t.Skip("optional example bundle is not present") + } t.Fatalf("read example bundle: %v", err) }