fix(parser): dedupe HPE AHS DIMM inventory per slot, newest snapshot wins
The AHS blackbox stores a DIMM inventory snapshot per POST cycle and parseDIMMs flattens all of them. dedupeMemory keyed on serial, so a slot whose module was swapped between captures survived once per historical occupant — a 24-slot board reported 26 modules and "same P/N" vs "mixed P/N" configs looked identical. dedupeMemory now collapses to one entry per non-empty slot with the last (most recent, since token order follows chronological blackbox-record order) occurrence winning. Slotless entries keep the serial/part fallback. See ADL-060. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
99d8f098ac
commit
632067fef5
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.mchus.pro/mchus/logpile/internal/models"
|
||||
"git.mchus.pro/mchus/logpile/internal/parser"
|
||||
)
|
||||
|
||||
@@ -153,6 +154,34 @@ func TestParseAHSInventory(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDedupeMemorySlotSwap(t *testing.T) {
|
||||
// The AHS blackbox keeps one inventory snapshot per POST cycle. When a module
|
||||
// is swapped between captures the same slot appears with different serials, in
|
||||
// chronological (token stream) order. dedupeMemory must keep one entry per
|
||||
// slot, with the most recent snapshot winning.
|
||||
items := []models.MemoryDIMM{
|
||||
{Slot: "PROC 1 DIMM 1", PartNumber: "HMCG94AHBRA480N", SerialNumber: "AAA1"},
|
||||
{Slot: "PROC 1 DIMM 7", PartNumber: "HMCG94AHBRA487N", SerialNumber: "OLD7"},
|
||||
{Slot: "PROC 1 DIMM 1", PartNumber: "HMCG94AHBRA480N", SerialNumber: "AAA1"}, // repeated snapshot
|
||||
{Slot: "PROC 1 DIMM 7", PartNumber: "HMCG94AHBRA480N", SerialNumber: "NEW7"}, // module swapped
|
||||
}
|
||||
|
||||
out := dedupeMemory(items)
|
||||
if len(out) != 2 {
|
||||
t.Fatalf("expected 2 DIMMs (one per slot), got %d: %+v", len(out), out)
|
||||
}
|
||||
bySlot := map[string]models.MemoryDIMM{}
|
||||
for _, d := range out {
|
||||
bySlot[d.Slot] = d
|
||||
}
|
||||
if got := bySlot["PROC 1 DIMM 7"].SerialNumber; got != "NEW7" {
|
||||
t.Fatalf("expected newest occupant NEW7 for slot 7, got %q", got)
|
||||
}
|
||||
if got := bySlot["PROC 1 DIMM 1"].SerialNumber; got != "AAA1" {
|
||||
t.Fatalf("unexpected serial for slot 1: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAHSTruncatedEntry(t *testing.T) {
|
||||
p := &Parser{}
|
||||
// Build archive where the last entry's declared size exceeds available data.
|
||||
|
||||
Reference in New Issue
Block a user