package h3c
import (
"strings"
"testing"
"git.mchus.pro/mchus/logpile/internal/models"
"git.mchus.pro/mchus/logpile/internal/parser"
)
func TestDetectH3C_GenerationRouting(t *testing.T) {
g5 := &G5Parser{}
g6 := &G6Parser{}
g5Files := []parser.ExtractedFile{
{Path: "bmc/pack.info", Content: []byte("STARTTIME:0")},
{Path: "static/FRUInfo.ini", Content: []byte("[Baseboard]\nBoard Manufacturer=H3C\n")},
{Path: "static/hardware_info.ini", Content: []byte("[Processors: Processor 1]\nModel: Intel Xeon\n")},
{Path: "static/hardware.info", Content: []byte("[Disk_0_Front_NA]\nSerialNumber=DISK-0\n")},
{Path: "static/firmware_version.ini", Content: []byte("[System board]\nBIOS Version: 5.59\n")},
{Path: "user/test1.csv", Content: []byte("Record Time Stamp,DescInfo\n2025-01-01 00:00:00,foo\n")},
}
if gotG5, gotG6 := g5.Detect(g5Files), g6.Detect(g5Files); gotG5 <= gotG6 {
t.Fatalf("expected G5 confidence > G6 for G5 sample, got g5=%d g6=%d", gotG5, gotG6)
}
g6Files := []parser.ExtractedFile{
{Path: "bmc/pack.info", Content: []byte("STARTTIME:0")},
{Path: "static/FRUInfo.ini", Content: []byte("[Baseboard]\nBoard Manufacturer=H3C\n")},
{Path: "static/board_info.ini", Content: []byte("[System board]\nBoardMfr=H3C\n")},
{Path: "static/firmware_version.json", Content: []byte(`{"BIOS":{"Firmware Name":"BIOS","Firmware Version":"6.10"}}`)},
{Path: "static/CPUDetailInfo.xml", Content: []byte("X")},
{Path: "static/MemoryDetailInfo.xml", Content: []byte("A0")},
{Path: "user/Sel.json", Content: []byte(`{"Id":1}`)},
}
if gotG5, gotG6 := g5.Detect(g6Files), g6.Detect(g6Files); gotG6 <= gotG5 {
t.Fatalf("expected G6 confidence > G5 for G6 sample, got g5=%d g6=%d", gotG5, gotG6)
}
}
func TestParseH3CG6_RaidAndNVMeEnrichment(t *testing.T) {
p := &G6Parser{}
files := []parser.ExtractedFile{
{
Path: "static/storage_disk.ini",
Content: []byte(`[Disk_000]
DiskSlotDesc=Front0
Present=YES
SerialNumber=SER-0
`),
},
{
Path: "static/raid.json",
Content: []byte(`{
"RaidConfig": {
"CtrlInfo": [
{
"CtrlSlot": 1,
"CtrlName": "RAID-LSI-9560",
"LDInfo": [
{
"LDID": "0",
"LDName": "VD0",
"RAIDLevel": "1",
"CapacityBytes": 1000000000,
"Status": "Optimal"
}
]
}
]
}
}`),
},
{
Path: "static/Storage_RAID-LSI-9560-LP-8i-4GB[1].txt",
Content: []byte(`Controller Information
------------------------------------------------------------------------
AssetTag : RAID-LSI-9560
Logical Device Information
------------------------------------------------------------------------
LDID : 0
Name : VD0
RAID Level : 1
CapacityBytes : 1000000000
Status : Optimal
Physical Device Information
------------------------------------------------------------------------
ConnectionID : 0
Position : Front0
StatusIndicator : OK
Protocol : SATA
MediaType : SSD
Manufacturer : Samsung
Model : PM893
Revision : GDC1
SerialNumber : SER-0
CapacityBytes : 480000000000
ConnectionID : 1
Position : Front1
StatusIndicator : OK
Protocol : SATA
MediaType : SSD
Manufacturer : Samsung
Model : PM893
Revision : GDC1
SerialNumber : SER-1
CapacityBytes : 480000000000
`),
},
{
Path: "static/NVMe_info.txt",
Content: []byte(`[NVMe_0]
Present=YES
DiskSlotDesc=Front2
Model=INTEL SSDPE2KX010T8
SerialNumber=NVME-1
Firmware=V100
CapacityBytes=1000204886016
Interface=NVMe
Status=OK
`),
},
}
result, err := p.Parse(files)
if err != nil {
t.Fatalf("parse failed: %v", err)
}
if result.Hardware == nil {
t.Fatalf("expected hardware section")
}
if len(result.Hardware.Volumes) != 1 {
t.Fatalf("expected 1 volume, got %d", len(result.Hardware.Volumes))
}
vol := result.Hardware.Volumes[0]
if vol.RAIDLevel != "RAID1" {
t.Fatalf("expected RAID1 level, got %q", vol.RAIDLevel)
}
if vol.SizeGB != 1 {
t.Fatalf("expected 1GB logical volume, got %d", vol.SizeGB)
}
if len(result.Hardware.Storage) != 3 {
t.Fatalf("expected 3 unique storage devices, got %d", len(result.Hardware.Storage))
}
var front0 *models.Storage
var nvme *models.Storage
for i := range result.Hardware.Storage {
s := &result.Hardware.Storage[i]
if strings.EqualFold(s.SerialNumber, "SER-0") {
front0 = s
}
if strings.EqualFold(s.SerialNumber, "NVME-1") {
nvme = s
}
}
if front0 == nil {
t.Fatalf("expected merged Front0 disk by serial SER-0")
}
if front0.Model != "PM893" {
t.Fatalf("expected Front0 model PM893, got %q", front0.Model)
}
if front0.SizeGB != 480 {
t.Fatalf("expected Front0 size 480GB, got %d", front0.SizeGB)
}
if nvme == nil {
t.Fatalf("expected NVMe disk by serial NVME-1")
}
if nvme.Type != "nvme" {
t.Fatalf("expected nvme type, got %q", nvme.Type)
}
}
func TestParseH3CG6(t *testing.T) {
p := &G6Parser{}
files := []parser.ExtractedFile{
{
Path: "static/FRUInfo.ini",
Content: []byte(`[Baseboard]
Board Manufacturer=H3C
Board Product Name=RS36M2C6SB
Product Product Name=H3C UniServer R4700 G6
Product Serial Number=210235A4FYH257000010
Product Part Number=0235A4FY
`),
},
{
Path: "static/firmware_version.json",
Content: []byte(`{
"BMCP": {"Firmware Name":"HDM","Firmware Version":"1.83","Location":"bmc card","Part Model":"-"},
"BIOS": {"Firmware Name":"BIOS","Firmware Version":"6.10.53","Location":"system board","Part Model":"-"}
}`),
},
{
Path: "static/CPUDetailInfo.xml",
Content: []byte(`
Presence
INTEL(R) XEON(R) GOLD 6542Y
0xb54
0x1004
0x18
0x30
68-5C-81-C1-0E-A3-4E-40
68-5C-81-C1-0E-A3-4E-40
`),
},
{
Path: "static/MemoryDetailInfo.xml",
Content: []byte(`
Presence
CPU1_CH1_D0 (A0)
M321R8GA0PB0-CWMXJ
RDIMM
80CE032519135C82ED
0x2
0x10000
0x1130
0x15e0
A0
`),
},
{
Path: "static/storage_disk.ini",
Content: []byte(`[Disk_000]
SerialNumber=S6KLNN0Y516813
DiskSlotDesc=Front0
Present=YES
`),
},
{
Path: "static/net_cfg.ini",
Content: []byte(`[Network Configuration]
eth0 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F6
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth0.2 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F6
inet6 addr: fe80::32c6:d7ff:fe94:54f6/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1496 Metric:1
eth1 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F5
inet addr:10.201.129.0 Bcast:10.201.143.255 Mask:255.255.240.0
inet6 addr: fe80::32c6:d7ff:fe94:54f5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
`),
},
{
Path: "static/psu_cfg.ini",
Content: []byte(`[Psu0]
SN=210231AGUNH257001569
Max_Power(W)=1600
Manufacturer=Great Wall
Power Status=Input Normal, Output Normal
Present_Status=Present
Power_ID=1
Model=GW-CRPS1600D2
Version=03.02.00
[Psu1]
Manufacturer=Great Wall
Power_ID=2
Version=03.02.00
Power Status=Input Normal, Output Normal
SN=210231AGUNH257001570
Model=GW-CRPS1600D2
Present_Status=Present
Max_Power(W)=1600
`),
},
{
Path: "static/hardware_info.ini",
Content: []byte(`[Ethernet adapters: Port 1]
Device Type : NIC
Network Port : Port 1
Location : PCIE-[1]
MAC Address : E4:3D:1A:6F:B0:30
Speed : 8.0GT/s
Product Name : NIC-BCM957414-F-B-25Gb-2P
[Ethernet adapters: Port 2]
Device Type : NIC
Network Port : Port 2
Location : PCIE-[1]
MAC Address : E4:3D:1A:6F:B0:31
Speed : 8.0GT/s
Product Name : NIC-BCM957414-F-B-25Gb-2P
[PCIe Card: PCIe 1]
Location : 1
Product Name : NIC-BCM957414-F-B-25Gb-2P
Status : Normal
Vendor ID : 0x14E4
Device ID : 0x16D7
Serial Number : NICSN-G6-001
Part Number : NICPN-G6-001
Firmware Version : 22.35.1010
`),
},
{
Path: "static/sensor_info.ini",
Content: []byte(`Sensor Name | Reading | Unit | Status| Crit low
Inlet_Temp | 20.000 | degrees C | ok | na
CPU1_Status | 0x0 | discrete | 0x8080| na
`),
},
{
Path: "user/Sel.json",
Content: []byte(`
{
"Created": "2025-07-14 03:34:18 UTC+08:00",
"Severity": "Info",
"EntryCode": "Asserted",
"EntryType": "Event",
"Id": 1,
"Level": "Info",
"Message": "Processor Presence detected",
"SensorName": "CPU1_Status",
"SensorType": "Processor"
},
{
"Created": "2025-07-14 20:56:45 UTC+08:00",
"Severity": "Critical",
"EntryCode": "Asserted",
"EntryType": "Event",
"Id": 2,
"Level": "Critical",
"Message": "Power Supply AC lost",
"SensorName": "PSU1_Status",
"SensorType": "Power Supply"
}
`),
},
}
result, err := p.Parse(files)
if err != nil {
t.Fatalf("parse failed: %v", err)
}
if result.Hardware == nil {
t.Fatalf("expected hardware section")
}
if result.Hardware.BoardInfo.Manufacturer != "H3C" {
t.Fatalf("unexpected board manufacturer: %q", result.Hardware.BoardInfo.Manufacturer)
}
if result.Hardware.BoardInfo.ProductName != "H3C UniServer R4700 G6" {
t.Fatalf("unexpected board product: %q", result.Hardware.BoardInfo.ProductName)
}
if result.Hardware.BoardInfo.SerialNumber != "210235A4FYH257000010" {
t.Fatalf("unexpected board serial: %q", result.Hardware.BoardInfo.SerialNumber)
}
if len(result.Hardware.Firmware) < 2 {
t.Fatalf("expected firmware entries, got %d", len(result.Hardware.Firmware))
}
if len(result.Hardware.CPUs) != 1 {
t.Fatalf("expected 1 cpu, got %d", len(result.Hardware.CPUs))
}
if result.Hardware.CPUs[0].Cores != 24 {
t.Fatalf("expected 24 cores, got %d", result.Hardware.CPUs[0].Cores)
}
if len(result.Hardware.Memory) != 1 {
t.Fatalf("expected 1 dimm, got %d", len(result.Hardware.Memory))
}
if result.Hardware.Memory[0].SizeMB != 65536 {
t.Fatalf("expected 65536MB, got %d", result.Hardware.Memory[0].SizeMB)
}
if len(result.Hardware.Storage) != 1 {
t.Fatalf("expected 1 disk, got %d", len(result.Hardware.Storage))
}
if result.Hardware.Storage[0].SerialNumber != "S6KLNN0Y516813" {
t.Fatalf("unexpected disk serial: %q", result.Hardware.Storage[0].SerialNumber)
}
if len(result.Hardware.PowerSupply) != 2 {
t.Fatalf("expected 2 PSUs from psu_cfg.ini, got %d", len(result.Hardware.PowerSupply))
}
if result.Hardware.PowerSupply[0].WattageW == 0 {
t.Fatalf("expected PSU wattage parsed, got 0")
}
if len(result.Hardware.NetworkAdapters) != 1 {
t.Fatalf("expected 1 host network adapter from hardware_info.ini, got %d", len(result.Hardware.NetworkAdapters))
}
macs := make(map[string]struct{})
var hostNIC models.NetworkAdapter
var hostNICFound bool
for _, nic := range result.Hardware.NetworkAdapters {
if len(nic.MACAddresses) == 0 {
t.Fatalf("expected MAC on network adapter %+v", nic)
}
for _, mac := range nic.MACAddresses {
macs[strings.ToLower(mac)] = struct{}{}
}
if strings.EqualFold(nic.Slot, "PCIe 1") && strings.Contains(strings.ToLower(nic.Model), "bcm957414") {
hostNIC = nic
hostNICFound = true
}
}
if !hostNICFound {
t.Fatalf("expected host NIC from hardware_info.ini, got %+v", result.Hardware.NetworkAdapters)
}
if _, ok := macs["e4:3d:1a:6f:b0:30"]; !ok {
t.Fatalf("expected host NIC MAC e4:3d:1a:6f:b0:30 in adapters, got %+v", result.Hardware.NetworkAdapters)
}
if _, ok := macs["e4:3d:1a:6f:b0:31"]; !ok {
t.Fatalf("expected host NIC MAC e4:3d:1a:6f:b0:31 in adapters, got %+v", result.Hardware.NetworkAdapters)
}
if !strings.Contains(strings.ToLower(hostNIC.Vendor), "broadcom") {
t.Fatalf("expected host NIC vendor enrichment from Vendor ID, got %q", hostNIC.Vendor)
}
if hostNIC.SerialNumber != "NICSN-G6-001" {
t.Fatalf("expected host NIC serial from PCIe card section, got %q", hostNIC.SerialNumber)
}
if hostNIC.PartNumber != "NICPN-G6-001" {
t.Fatalf("expected host NIC part number from PCIe card section, got %q", hostNIC.PartNumber)
}
if hostNIC.Firmware != "22.35.1010" {
t.Fatalf("expected host NIC firmware from PCIe card section, got %q", hostNIC.Firmware)
}
if len(result.Sensors) != 2 {
t.Fatalf("expected 2 sensors, got %d", len(result.Sensors))
}
if result.Sensors[0].Name != "Inlet_Temp" {
t.Fatalf("unexpected first sensor: %q", result.Sensors[0].Name)
}
if len(result.Events) != 2 {
t.Fatalf("expected 2 events, got %d", len(result.Events))
}
if result.Events[0].Timestamp.Year() != 2025 || result.Events[0].Timestamp.Month() != 7 {
t.Fatalf("expected SEL timestamp from payload, got %s", result.Events[0].Timestamp)
}
if result.Events[1].Severity != models.SeverityCritical {
t.Fatalf("expected critical severity for AC lost event, got %q", result.Events[1].Severity)
}
}
func TestParseH3CG5_PCIeArgumentsEnrichesNonNVMeStorage(t *testing.T) {
p := &G5Parser{}
files := []parser.ExtractedFile{
{
Path: "static/storage_disk.ini",
Content: []byte(`[Disk_000]
DiskSlotDesc=Front slot 3
Present=YES
SerialNumber=SAT-03
`),
},
{
Path: "static/NVMe_info.txt",
Content: []byte(`[NVMe_0]
Present=YES
DiskSlotDesc=Front slot 108
SerialNumber=NVME-108
`),
},
{
Path: "static/PCIe_arguments_table.xml",
Content: []byte(`
SSD
SSD-SATA-960G
0x144D
SSD
SSD-3.84T-NVMe-SFF
0x144D
`),
},
}
result, err := p.Parse(files)
if err != nil {
t.Fatalf("parse failed: %v", err)
}
if result.Hardware == nil {
t.Fatalf("expected hardware section")
}
if len(result.Hardware.Storage) != 2 {
t.Fatalf("expected 2 storage devices, got %d", len(result.Hardware.Storage))
}
var sata *models.Storage
var nvme *models.Storage
for i := range result.Hardware.Storage {
s := &result.Hardware.Storage[i]
switch s.SerialNumber {
case "SAT-03":
sata = s
case "NVME-108":
nvme = s
}
}
if sata == nil {
t.Fatalf("expected SATA storage SAT-03")
}
if sata.Model != "SSD-SATA-960G" {
t.Fatalf("expected SATA model enrichment from PCIe table, got %q", sata.Model)
}
if !strings.Contains(strings.ToLower(sata.Manufacturer), "samsung") {
t.Fatalf("expected SATA vendor enrichment to Samsung, got %q", sata.Manufacturer)
}
if nvme == nil {
t.Fatalf("expected NVMe storage NVME-108")
}
if nvme.Model != "SSD-3.84T-NVMe-SFF" {
t.Fatalf("expected NVMe model enrichment from PCIe table, got %q", nvme.Model)
}
if !strings.Contains(strings.ToLower(nvme.Manufacturer), "samsung") {
t.Fatalf("expected NVMe vendor enrichment to Samsung, got %q", nvme.Manufacturer)
}
}
func TestParseH3CG5_VariantLayout(t *testing.T) {
p := &G5Parser{}
files := []parser.ExtractedFile{
{
Path: "static/FRUInfo.ini",
Content: []byte(`[Baseboard]
Board Manufacturer=H3C
Product Product Name=H3C UniServer R4900 G5
Product Serial Number=02A6AX5231C003VM
`),
},
{
Path: "static/firmware_version.ini",
Content: []byte(`[System board]
BIOS Version : 5.59 V100R001B05D078
ME Version : 4.4.4.202
HDM Version : 3.34.01 HDM V100R001B05D078SP01
CPLD Version : V00C
`),
},
{
Path: "static/board_cfg.ini",
Content: []byte(`[Board Type]
Board Type : R4900 G5
[Board Version]
Board Version : VER.D
[Customer ID]
CustomerID : 255
[OEM ID]
OEM Flag : 1
`),
},
{
Path: "static/hardware_info.ini",
Content: []byte(`[Processors: Processor 1]
Model : Intel(R) Xeon(R) Gold 6342 CPU @ 2.80GHz
Status : Normal
Frequency : 2800 MHz
Cores : 24
Threads : 48
L1 Cache : 1920 KB
L2 Cache : 30720 KB
L3 Cache : 36864 KB
CPU PPIN : 49-A9-50-C0-15-9F-2D-DC
[Processors: Processor 2]
Model : Intel(R) Xeon(R) Gold 6342 CPU @ 2.80GHz
Status : Normal
Frequency : 2800 MHz
Cores : 24
Threads : 48
CPU PPIN : 49-AC-3D-BF-85-7F-17-58
[Memory Details: Dimm Index 0]
Location : Processor 1
Channel : 1
Socket ID : A0
Status : Normal
Size : 65536 MB
Maximum Frequency : 3200 MHz
Type : DDR4
Ranks : 2R DIMM
Technology : RDIMM
Part Number : M393A8G40AB2-CWE
Manufacture : Samsung
Serial Number : S02K0D0243351D7079
[Memory Details: Dimm Index 16]
Location : Processor 2
Channel : 1
Socket ID : A0
Status : Normal
Size : 65536 MB
Maximum Frequency : 3200 MHz
Type : DDR4
Ranks : 2R DIMM
Technology : RDIMM
Part Number : M393A8G40AB2-CWE
Manufacture : Samsung
Serial Number : S02K0D0243351D73F0
[Ethernet adapters: Port 1]
Device Type : NIC
Network Port : Port 1
Location : PCIE-[1]
MAC Address : E4:3D:1A:6F:B0:30
Speed : 8.0GT/s
Product Name : NIC-BCM957414-F-B-25Gb-2P
[Ethernet adapters: Port 2]
Device Type : NIC
Network Port : Port 2
Location : PCIE-[1]
MAC Address : E4:3D:1A:6F:B0:31
Speed : 8.0GT/s
Product Name : NIC-BCM957414-F-B-25Gb-2P
[Ethernet adapters: Port 1]
Device Type : NIC
Network Port : Port 1
Location : PCIE-[4]
MAC Address : E8:EB:D3:4F:2E:90
Speed : 8.0GT/s
Product Name : NIC-MCX512A-ACAT-2*25Gb-F
[Ethernet adapters: Port 2]
Device Type : NIC
Network Port : Port 2
Location : PCIE-[4]
MAC Address : E8:EB:D3:4F:2E:91
Speed : 8.0GT/s
Product Name : NIC-MCX512A-ACAT-2*25Gb-F
[PCIe Card: PCIe 1]
Location : 1
Product Name : NIC-BCM957414-F-B-25Gb-2P
Status : Normal
Vendor ID : 0x14E4
Device ID : 0x16D7
Serial Number : NICSN-G5-001
Part Number : NICPN-G5-001
Firmware Version : 21.80.1
[PCIe Card: PCIe 4]
Location : 4
Product Name : NIC-MCX512A-ACAT-2*25Gb-F
Status : Normal
Vendor ID : 0x15B3
Device ID : 0x1017
Serial Number : NICSN-G5-004
Part Number : NICPN-G5-004
Firmware Version : 28.33.15
`),
},
{
Path: "static/hardware.info",
Content: []byte(`[Disk_0_Front_NA]
Present=YES
SlotNum=0
FrontOrRear=Front
SerialNumber=22443C4EE184
[Nvme_Front slot 21]
Present=YES
NvmePhySlot=Front slot 21
SlotNum=121
SerialNumber=NVME-21
[Nvme_255_121]
Present=YES
SlotNum=121
SerialNumber=NVME-21
`),
},
{
Path: "static/raid.json",
Content: []byte(`{
"RAIDCONFIG": {
"Ctrl info": [
{
"CtrlDevice Slot": 3,
"CtrlDevice Name": "AVAGO MegaRAID SAS 9460-8i",
"LDInfo": [
{
"LD ID": 0,
"LD_name": "SystemRAID",
"RAID_level(RAID 0,RAID 1,RAID 5,RAID 6,RAID 00,RAID 10,RAID 50,RAID 60)": "RAID1",
"Logical_capicity(per 512byte)": 936640512
}
]
},
{
"CtrlDevice Slot": 6,
"CtrlDevice Name": "MegaRAID 9560-16i 8GB",
"LDInfo": [
{
"LD ID": 0,
"LD_name": "DataRAID",
"RAID_level(RAID 0,RAID 1,RAID 5,RAID 6,RAID 00,RAID 10,RAID 50,RAID 60)": "RAID50",
"Logical_capicity(per 512byte)": 90004783104
}
]
}
]
}
}`),
},
{
Path: "static/Raid_BP_Conf_Info.ini",
Content: []byte(`[BP Information]
Description | BP TYPE | I2cPort | BpConnectorNum | FrontOrRear | Node Num | DiskSlotRange |
8SFF SAS/SATA | BP_G5_8SFF | AUX_1 | ~ | ~ | ~ | ~ |
8SFF SAS/SATA | BP_G5_8SFF | AUX_2 | ~ | ~ | ~ | ~ |
8SFF SAS/SATA | BP_G5_8SFF | AUX_3 | ~ | ~ | ~ | ~ |
[RAID Information]
PCIE SLOT | RAID SAS_NUM |
3 | 2 |
6 | 4 |
`),
},
{
Path: "static/PCIe_arguments_table.xml",
Content: []byte(`
SSD
SSD-1.92T/3.84T-NVMe-EV-SFF-sa
0x144D
`),
},
{
Path: "static/psu_cfg.ini",
Content: []byte(`[Active / Standby configuration]
Power ID : 1
Present Status : Present
Cold Status : Active Power
Model : DPS-1300AB-6 R
SN : 210231ACT9H232000080
Max Power(W) : 1300
Power ID : 2
Present Status : Present
Cold Status : Active Power
Model : DPS-1300AB-6 R
SN : 210231ACT9H232000079
Max Power(W) : 1300
`),
},
{
Path: "static/net_cfg.ini",
Content: []byte(`[Network Configuration]
eth0 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F6
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
eth0.2 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F6
inet6 addr: fe80::32c6:d7ff:fe94:54f6/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1496 Metric:1
eth1 Link encap:Ethernet HWaddr 30:C6:D7:94:54:F5
inet addr:10.201.129.0 Bcast:10.201.143.255 Mask:255.255.240.0
inet6 addr: fe80::32c6:d7ff:fe94:54f5/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
`),
},
{
Path: "static/smartdata/Front0/first_date_analysis.txt",
Content: []byte(`The Current System Time Is 2023_09_22_14_19_39
Model Info: ATA Micron_5300_MTFD
Serial Number: 22443C4EE184
`),
},
{
Path: "user/test1.csv",
Content: []byte(`Record Time Stamp,Severity Level,Severity Level ID,SensorTypeStr,SensorName,Event Dir,Event Occurred Time,DescInfo,Explanation,Suggestion
2025-04-01 08:50:13,Minor,0x1,NA,NA,NA,2025-04-01 08:50:13,"SSH login failed from IP: 10.200.10.121 user: admin"," "," "
Pre-Init,Info,0x0,Management Subsystem Health,Health,Assertion event,Pre-Init,"Management controller off-line"," "," "
2025-04-01 08:51:10,Major,0x2,Power Supply,PSU1_Status,Assertion event,2025-04-01 08:51:10,"Power Supply AC lost"," "," "
`),
},
}
result, err := p.Parse(files)
if err != nil {
t.Fatalf("parse failed: %v", err)
}
if result.Hardware == nil {
t.Fatalf("expected hardware section")
}
if len(result.Hardware.CPUs) != 2 {
t.Fatalf("expected 2 CPUs from hardware_info.ini, got %d", len(result.Hardware.CPUs))
}
if result.Hardware.CPUs[0].FrequencyMHz != 2800 {
t.Fatalf("expected CPU frequency 2800MHz, got %d", result.Hardware.CPUs[0].FrequencyMHz)
}
if len(result.Hardware.Memory) != 2 {
t.Fatalf("expected 2 DIMMs from hardware_info.ini, got %d", len(result.Hardware.Memory))
}
if result.Hardware.Memory[0].SizeMB != 65536 {
t.Fatalf("expected DIMM size 65536MB, got %d", result.Hardware.Memory[0].SizeMB)
}
if len(result.Hardware.Firmware) < 4 {
t.Fatalf("expected firmware entries from firmware_version.ini, got %d", len(result.Hardware.Firmware))
}
if result.Hardware.BoardInfo.Version == "" {
t.Fatalf("expected board version from board_cfg.ini")
}
if !strings.Contains(result.Hardware.BoardInfo.Description, "CustomerID: 255") {
t.Fatalf("expected board description enrichment from board_cfg.ini, got %q", result.Hardware.BoardInfo.Description)
}
if len(result.Hardware.Storage) != 2 {
t.Fatalf("expected 2 unique storage devices from hardware.info, got %d", len(result.Hardware.Storage))
}
var nvmeFound bool
var diskModelEnriched bool
for _, s := range result.Hardware.Storage {
if s.SerialNumber == "NVME-21" {
nvmeFound = true
if s.Type != "nvme" {
t.Fatalf("expected NVME-21 type nvme, got %q", s.Type)
}
if !strings.Contains(strings.ToLower(s.Manufacturer), "samsung") {
t.Fatalf("expected NVME vendor enrichment to Samsung, got %q", s.Manufacturer)
}
if s.Model != "SSD-1.92T/3.84T-NVMe-EV-SFF-sa" {
t.Fatalf("expected NVME model enrichment from PCIe table, got %q", s.Model)
}
}
if s.SerialNumber == "22443C4EE184" && strings.Contains(s.Model, "Micron") {
diskModelEnriched = true
}
}
if !nvmeFound {
t.Fatalf("expected deduped NVME storage by serial NVME-21")
}
if !diskModelEnriched {
t.Fatalf("expected disk model enrichment from smartdata by serial")
}
if len(result.Hardware.PowerSupply) != 2 {
t.Fatalf("expected 2 PSUs from psu_cfg.ini, got %d", len(result.Hardware.PowerSupply))
}
if result.Hardware.PowerSupply[0].WattageW == 0 {
t.Fatalf("expected PSU wattage parsed, got 0")
}
if len(result.Hardware.NetworkAdapters) != 2 {
t.Fatalf("expected 2 host network adapters from hardware_info.ini, got %d", len(result.Hardware.NetworkAdapters))
}
if len(result.Hardware.NetworkCards) != 2 {
t.Fatalf("expected 2 network cards synthesized from adapters, got %d", len(result.Hardware.NetworkCards))
}
var g5NIC models.NetworkAdapter
var g5NICFound bool
for _, nic := range result.Hardware.NetworkAdapters {
if strings.EqualFold(nic.Slot, "PCIe 1") && strings.Contains(strings.ToLower(nic.Model), "bcm957414") {
g5NIC = nic
g5NICFound = true
break
}
}
if !g5NICFound {
t.Fatalf("expected host NIC PCIe 1 from hardware_info.ini, got %+v", result.Hardware.NetworkAdapters)
}
if !strings.Contains(strings.ToLower(g5NIC.Vendor), "broadcom") {
t.Fatalf("expected G5 NIC vendor from Vendor ID, got %q", g5NIC.Vendor)
}
if g5NIC.SerialNumber != "NICSN-G5-001" {
t.Fatalf("expected G5 NIC serial from PCIe card section, got %q", g5NIC.SerialNumber)
}
if g5NIC.PartNumber != "NICPN-G5-001" {
t.Fatalf("expected G5 NIC part number from PCIe card section, got %q", g5NIC.PartNumber)
}
if g5NIC.Firmware != "21.80.1" {
t.Fatalf("expected G5 NIC firmware from PCIe card section, got %q", g5NIC.Firmware)
}
if len(result.Hardware.Devices) != 5 {
t.Fatalf("expected 5 topology devices from Raid_BP_Conf_Info.ini (3 BP + 2 RAID), got %d", len(result.Hardware.Devices))
}
var bpFound bool
var raidFound bool
for _, d := range result.Hardware.Devices {
if strings.Contains(d.ID, "h3c-bp-") && strings.Contains(d.Model, "BP_G5_8SFF") {
bpFound = true
}
desc, _ := d.Details["description"].(string)
if strings.Contains(d.ID, "h3c-raid-slot-3") && strings.Contains(desc, "SAS ports: 2") {
raidFound = true
}
}
if !bpFound || !raidFound {
t.Fatalf("expected parsed backplane and RAID topology devices, got %+v", result.Hardware.Devices)
}
if len(result.Hardware.Volumes) != 2 {
t.Fatalf("expected 2 RAID volumes (same LD ID on different controllers), got %d", len(result.Hardware.Volumes))
}
var raid1Found bool
var raid50Found bool
for _, v := range result.Hardware.Volumes {
if strings.Contains(v.Controller, "slot 3") {
raid1Found = v.RAIDLevel == "RAID1" && v.CapacityBytes > 0
}
if strings.Contains(v.Controller, "slot 6") {
raid50Found = v.RAIDLevel == "RAID50" && v.CapacityBytes > 0
}
}
if !raid1Found || !raid50Found {
t.Fatalf("expected RAID1 and RAID50 volumes with parsed capacities, got %+v", result.Hardware.Volumes)
}
if len(result.Events) != 2 {
t.Fatalf("expected 2 CSV events (Pre-Init skipped), got %d", len(result.Events))
}
if result.Events[0].Severity != models.SeverityWarning {
t.Fatalf("expected Minor CSV severity mapped to warning, got %q", result.Events[0].Severity)
}
if result.Events[1].Severity != models.SeverityCritical {
t.Fatalf("expected Major CSV severity mapped to critical, got %q", result.Events[1].Severity)
}
}