package dell import ( "archive/zip" "bytes" "testing" "git.mchus.pro/mchus/logpile/internal/parser" ) func TestDetectNestedTSRZip(t *testing.T) { inner := makeZipArchive(t, map[string][]byte{ "tsr/metadata.json": []byte(`{"Make":"Dell Inc.","Model":"PowerEdge R750","ServiceTag":"G37Q064"}`), "tsr/hardware/sysinfo/inventory/sysinfo_DCIM_View.xml": []byte(``), }) p := &Parser{} score := p.Detect([]parser.ExtractedFile{ {Path: "signature", Content: []byte("ok")}, {Path: "TSR20241119143901_G37Q064.pl.zip", Content: inner}, }) if score < 80 { t.Fatalf("expected high detect score for nested TSR zip, got %d", score) } } func TestParseNestedTSRZip(t *testing.T) { const viewXML = ` Dell Inc. PowerEdge R750 G37Q064 2.19.1 7.00.30.00 CPU.Socket.1 Intel(R) Xeon(R) Gold 6330 Intel 28 56 2000 3100 ABCD NIC.Slot.1-1-1 Broadcom 57414 Dual Port 10/25GbE SFP28 Adapter Broadcom 00:11:22:33:44:55 NICSERIAL1 22.80.17 0x14e4 0x16d7 PSU.Slot.1 D1400E-S0 Dell PSUSERIAL1 00.1A 1400 Video.Slot.38-1 NVIDIA H100 PCIe GH100 [H100 PCIe] NVIDIA Corporation 10DE 2331 74 0 0 1793924039808 96.00.AF.00.01 bc681a6d4785dde08c21f49c46c05cc3 ` const swXML = ` NIC.Slot.1-1-1 22.80.17 Network ` const eventsXML = ` SYS1001 Link is down NIC.Slot.1-1-1 ` const cimSensorXML = ` Video.Slot.38-1 290 440 295 5 PS1 Voltage 1 224.0 5 0 5 ` inner := makeZipArchive(t, map[string][]byte{ "tsr/metadata.json": []byte(`{ "Make":"Dell Inc.", "Model":"PowerEdge R750", "ServiceTag":"G37Q064", "FirmwareVersion":"7.00.30.00", "CollectionDateTime":"2024-11-19 14:39:01.000-0800" }`), "tsr/hardware/sysinfo/inventory/sysinfo_DCIM_View.xml": []byte(viewXML), "tsr/hardware/sysinfo/inventory/sysinfo_DCIM_SoftwareIdentity.xml": []byte(swXML), "tsr/hardware/sysinfo/inventory/sysinfo_CIM_Sensor.xml": []byte(cimSensorXML), "tsr/hardware/sysinfo/lcfiles/curr_lclog.xml": []byte(eventsXML), }) p := &Parser{} result, err := p.Parse([]parser.ExtractedFile{ {Path: "signature", Content: []byte("ok")}, {Path: "TSR20241119143901_G37Q064.pl.zip", Content: inner}, }) if err != nil { t.Fatalf("parse failed: %v", err) } if result.Hardware == nil { t.Fatalf("expected hardware section") } if got := result.Hardware.BoardInfo.Manufacturer; got != "Dell Inc." { t.Fatalf("unexpected board manufacturer: %q", got) } if got := result.Hardware.BoardInfo.ProductName; got != "PowerEdge R750" { t.Fatalf("unexpected board product: %q", got) } if got := result.Hardware.BoardInfo.SerialNumber; got != "G37Q064" { t.Fatalf("unexpected service tag: %q", got) } if len(result.Hardware.CPUs) != 1 { t.Fatalf("expected 1 cpu, got %d", len(result.Hardware.CPUs)) } if got := result.Hardware.CPUs[0].Model; got != "Intel(R) Xeon(R) Gold 6330" { t.Fatalf("unexpected cpu model: %q", got) } if len(result.Hardware.NetworkAdapters) != 1 { t.Fatalf("expected 1 network adapter, got %d", len(result.Hardware.NetworkAdapters)) } adapter := result.Hardware.NetworkAdapters[0] if adapter.Vendor != "Broadcom" { t.Fatalf("unexpected nic vendor: %q", adapter.Vendor) } if adapter.Firmware != "22.80.17" { t.Fatalf("unexpected nic firmware: %q", adapter.Firmware) } if adapter.SerialNumber != "NICSERIAL1" { t.Fatalf("unexpected nic serial: %q", adapter.SerialNumber) } if len(result.Hardware.PowerSupply) != 1 { t.Fatalf("expected 1 psu, got %d", len(result.Hardware.PowerSupply)) } psu := result.Hardware.PowerSupply[0] if psu.Model != "D1400E-S0" { t.Fatalf("unexpected psu model: %q", psu.Model) } if psu.Firmware != "00.1A" { t.Fatalf("unexpected psu firmware: %q", psu.Firmware) } if len(result.Hardware.Firmware) == 0 { t.Fatalf("expected firmware entries") } if len(result.Hardware.GPUs) != 1 { t.Fatalf("expected 1 gpu, got %d", len(result.Hardware.GPUs)) } if got := result.Hardware.GPUs[0].Model; got != "NVIDIA H100 PCIe" { t.Fatalf("unexpected gpu model: %q", got) } if got := result.Hardware.GPUs[0].SerialNumber; got != "1793924039808" { t.Fatalf("unexpected gpu serial: %q", got) } if got := result.Hardware.GPUs[0].Temperature; got != 29 { t.Fatalf("unexpected gpu temperature: %d", got) } if len(result.Sensors) == 0 { t.Fatalf("expected sensors from CIM_Sensor") } if len(result.Events) != 1 { t.Fatalf("expected one lifecycle event, got %d", len(result.Events)) } if got := string(result.Events[0].Severity); got != "warning" { t.Fatalf("unexpected event severity: %q", got) } } func makeZipArchive(t *testing.T, files map[string][]byte) []byte { t.Helper() var buf bytes.Buffer zw := zip.NewWriter(&buf) for name, content := range files { w, err := zw.Create(name) if err != nil { t.Fatalf("create zip entry %s: %v", name, err) } if _, err := w.Write(content); err != nil { t.Fatalf("write zip entry %s: %v", name, err) } } if err := zw.Close(); err != nil { t.Fatalf("close zip: %v", err) } return buf.Bytes() }