Files
logpile/internal/parser/vendors/inspur/sel_test.go
T
Mikhail ChusavitinandClaude Sonnet 5 e7b8a8badc feat(inspur): source-PRI timezone timeline, PPIN serial, NVMe fault storage status
Event ingestion now uses the source syslog PRI and an explicit-offset
timezone timeline instead of assuming host-local time. CPU PPIN is
exported as the source-backed CPU serial, and an active NVMe fault SEL
event promotes the matching drive's storage status.

See ADL-056, ADL-057.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 17:05:45 +03:00

86 lines
3.5 KiB
Go

package inspur
import (
"testing"
"time"
"git.mchus.pro/mchus/logpile/internal/models"
"git.mchus.pro/mchus/logpile/internal/parser"
)
func TestDedupSELEvents(t *testing.T) {
ts := time.Date(2026, 7, 27, 4, 52, 55, 0, time.UTC)
events := []models.Event{
{Source: "BMC", Timestamp: ts, EventType: "Assert", Severity: models.SeverityCritical, Description: "Sys_Health Transition to Critical from less severe"},
{Source: "SEL", Timestamp: ts, EventType: "Transition to Critical from less severe", Severity: models.SeverityCritical, Description: "Transition to Critical from less severe", RawData: "Asserted"},
{Source: "SEL", Timestamp: ts.Add(time.Second), EventType: "Asserted", Description: "PSU0 fail"},
{Source: "SEL", Timestamp: ts.Add(time.Second), EventType: "Asserted", Description: "PSU0 fail"},
{Source: "BMC", Timestamp: ts.Add(2 * time.Second), EventType: "Assert", Description: "recurring alarm"},
{Source: "BMC", Timestamp: ts.Add(2 * time.Second), EventType: "Assert", Description: "recurring alarm"},
}
out := dedupSELEvents(events)
if len(out) != 4 {
t.Fatalf("expected IDL/SEL copy and exact SEL copy removed, recurring BMC alarms retained; got %d: %+v", len(out), out)
}
if out[0].Source != "BMC" {
t.Fatalf("expected richer IDL/BMC event to be retained, got %+v", out[0])
}
}
func TestParseSELListWithLocation_UsesProvidedTimezone(t *testing.T) {
content := []byte("sel elist:\n1,02/28/2026,04:18:18,Sensor X,Event,Asserted\n")
shanghai, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
t.Fatalf("load location: %v", err)
}
events := ParseSELListWithLocation(content, shanghai)
if len(events) != 1 {
t.Fatalf("expected 1 event, got %d", len(events))
}
// 04:18:18 +08:00 == 20:18:18Z (previous day)
want := time.Date(2026, 2, 27, 20, 18, 18, 0, time.UTC)
if !events[0].Timestamp.UTC().Equal(want) {
t.Fatalf("unexpected timestamp: got %s want %s", events[0].Timestamp.UTC(), want)
}
}
func TestParseTimezoneConfigLocation(t *testing.T) {
content := []byte("[TimeZoneConfig]\ntimezone=Asia/Shanghai\n")
got := parseTimezoneConfigLocation(content)
if got != "Asia/Shanghai" {
t.Fatalf("unexpected timezone: %q", got)
}
}
func TestSELTimezoneResolverUsesExplicitOffsetTimeline(t *testing.T) {
files := []parser.ExtractedFile{
{Path: "onekeylog/configuration/conf/timezone.conf", Content: []byte("[TimeZoneConfig]\ntimezone=Asia/Shanghai\n")},
{Path: "onekeylog/log/syslog/idl.log", Content: []byte(
"|2026-01-30T14:25:14+08:00|BMC|Assert|Info|1|old timezone|\n" +
"|2026-07-24T02:20:38+03:00|BMC|Assert|Critical|2|new timezone|\n")},
}
fallback := inferInspurArchiveLocation(files)
resolver := inferInspurTimezoneResolver(files, fallback)
events := parseSELListWithResolver([]byte("sel elist:\n"+
"1,01/30/2026,14:25:14,Chassis Sys_Health,old timezone,Asserted\n"+
"2,07/24/2026,02:20:38,Chassis Sys_Health,new timezone,Asserted\n"), resolver)
if len(events) != 2 {
t.Fatalf("expected 2 events, got %d", len(events))
}
wantOld := time.Date(2026, 1, 30, 6, 25, 14, 0, time.UTC)
wantNew := time.Date(2026, 7, 23, 23, 20, 38, 0, time.UTC)
if !events[0].Timestamp.UTC().Equal(wantOld) || !events[1].Timestamp.UTC().Equal(wantNew) {
t.Fatalf("unexpected resolved timestamps: got %s and %s", events[0].Timestamp.UTC(), events[1].Timestamp.UTC())
}
}
func TestDetermineSELSeverityDeassertedFaultIsInfo(t *testing.T) {
got := determineSELSeverity("Power Supply PSU0", "Failure detected", "Deasserted")
if got != models.SeverityInfo {
t.Fatalf("expected cleared fault to be info, got %q", got)
}
}