package agentapi import "testing" func ip(v int) *int { return &v } // Verdict table (Part 2, extended v0.215.0). Red-proof: change the PercentageUsed boundary from // `>= 90` to `> 90` in DiskVerdictFor → the "NVMe percentage_used exactly 90 → Figyelmeztetés" case // fails. // // v0.215.0 moved ONE pre-existing case deliberately: critical_warning>0 was Figyelmeztetés and is // now Hiba (truth-table row 4). It is NVMe's own critical flag — a declaration by the device, not a // counter that might drift back — so it belongs with the self-reported failures, not below them. func TestDiskVerdictFor(t *testing.T) { noPrior := DiskPrior{} cases := []struct { name string in *SmartSummary prior DiskPrior want DiskVerdict }{ {"nil → unknown", nil, noPrior, DiskVerdictUnknown}, {"empty health → unknown", &SmartSummary{Health: ""}, noPrior, DiskVerdictUnknown}, {"UNKNOWN → unknown", &SmartSummary{Health: SmartUnknown}, noPrior, DiskVerdictUnknown}, {"FAILING → fail", &SmartSummary{Health: SmartFailing}, noPrior, DiskVerdictFail}, {"FAILING beats counters", &SmartSummary{Health: SmartFailing, ReallocatedSectors: ip(0)}, noPrior, DiskVerdictFail}, {"PASSED clean → ok", &SmartSummary{Health: SmartPassed, ReallocatedSectors: ip(0), PendingSectors: ip(0), TemperatureC: ip(30)}, noPrior, DiskVerdictOK}, {"PASSED nil counters → ok", &SmartSummary{Health: SmartPassed}, noPrior, DiskVerdictOK}, {"reallocated>0 alone → warn", &SmartSummary{Health: SmartPassed, ReallocatedSectors: ip(1)}, noPrior, DiskVerdictWarn}, {"pending>0 first sighting → warn", &SmartSummary{Health: SmartPassed, PendingSectors: ip(5)}, noPrior, DiskVerdictWarn}, {"offline_unc>0 first sighting → warn", &SmartSummary{Health: SmartPassed, OfflineUncorrectable: ip(2)}, noPrior, DiskVerdictWarn}, {"critical_warning>0 → fail (row 4)", &SmartSummary{Health: SmartPassed, CriticalWarning: ip(1)}, noPrior, DiskVerdictFail}, {"media_errors>0 → warn", &SmartSummary{Health: SmartPassed, MediaErrors: ip(3)}, noPrior, DiskVerdictWarn}, {"percentage_used 89 → ok", &SmartSummary{Health: SmartPassed, PercentageUsed: ip(89)}, noPrior, DiskVerdictOK}, {"percentage_used exactly 90 → warn", &SmartSummary{Health: SmartPassed, PercentageUsed: ip(90)}, noPrior, DiskVerdictWarn}, {"percentage_used 95 → warn", &SmartSummary{Health: SmartPassed, PercentageUsed: ip(95)}, noPrior, DiskVerdictWarn}, {"percentage_used exactly 100 → fail (row 5)", &SmartSummary{Health: SmartPassed, PercentageUsed: ip(100)}, noPrior, DiskVerdictFail}, } for _, c := range cases { if got := DiskVerdictFor(c.in, c.prior); got != c.want { t.Errorf("%s: DiskVerdictFor = %d, want %d", c.name, got, c.want) } } } func TestDiskVerdict_Label(t *testing.T) { want := map[DiskVerdict]string{ DiskVerdictUnknown: "Nincs adat", DiskVerdictOK: "Rendben", DiskVerdictWarn: "Figyelmeztetés", DiskVerdictFail: "Hiba", } for v, w := range want { if got := v.Label(); got != w { t.Errorf("verdict %d Label = %q, want %q", v, got, w) } } } // A warn lists every triggering attribute at once (Scenario "multiple attributes degrade" → ONE event). func TestDegradedAttributes_ListsAll(t *testing.T) { s := &SmartSummary{Health: SmartPassed, PendingSectors: ip(5), ReallocatedSectors: ip(2), PercentageUsed: ip(91)} got := DegradedAttributes(s) if len(got) != 3 { t.Fatalf("want 3 attributes, got %d: %v", len(got), got) } // clean disk → none if a := DegradedAttributes(&SmartSummary{Health: SmartPassed}); len(a) != 0 { t.Errorf("clean disk should list no attributes, got %v", a) } }