Release 0.0.5: health report (M4), installer (M9), update check (M13)
release / release (push) Successful in 13s
release / release (push) Successful in 13s
M4 — health report (the 0.0.4 CHANGELOG entry, folded into this release):
- core/health.py: scan journalctl (Xid/panic/OOM/MCE/AER/thermal), SMART,
NVIDIA driver mismatch, journald persistence, live temps -> findings
- CLI `rigdoctor report` (text/JSON); GUI Health tab; scanner tests
M9 — installer (first cut):
- core/{catalog,sysenv,installer}.py; `rigdoctor install [--check] [-y]`
- GUI Setup tab: detect distro/GPU, show optional components, one-click
install of missing apt packages via pkexec/sudo
M13 — update check (check half):
- core/updates.py; sidebar shows up-to-date / "Update to v…" / unavailable
Plus tests, version bump to 0.0.5, CHANGELOG, and doc status updates.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
"""Tests for the M4 health report's log scanner (synthetic input)."""
|
||||
|
||||
import unittest
|
||||
|
||||
from rigdoctor.core.health import CRITICAL, WARNING, run_health_checks, scan_journal_text
|
||||
|
||||
|
||||
class HealthScanTests(unittest.TestCase):
|
||||
def test_xid_79_is_critical(self):
|
||||
text = "NVRM: Xid (PCI:0000:01:00): 79, pid=1234, GPU has fallen off the bus."
|
||||
findings = scan_journal_text(text)
|
||||
gpu = [f for f in findings if f.category == "GPU"]
|
||||
self.assertEqual(len(gpu), 1)
|
||||
self.assertIn("79", gpu[0].title)
|
||||
self.assertEqual(gpu[0].severity, CRITICAL)
|
||||
|
||||
def test_xid_count_aggregates(self):
|
||||
text = "\n".join(["NVRM: Xid (PCI:0000:01:00): 79, foo"] * 3)
|
||||
gpu = [f for f in scan_journal_text(text) if f.category == "GPU"][0]
|
||||
self.assertIn("×3", gpu.title)
|
||||
|
||||
def test_oom_and_panic_detected(self):
|
||||
text = "Out of memory: Killed process 999 (game)\nKernel panic - not syncing: x"
|
||||
cats = {f.category for f in scan_journal_text(text)}
|
||||
self.assertIn("Memory", cats)
|
||||
self.assertIn("Kernel", cats)
|
||||
|
||||
def test_mce_critical(self):
|
||||
findings = scan_journal_text("mce: [Hardware Error]: Machine check events logged")
|
||||
self.assertTrue(any(f.severity == CRITICAL and f.category == "Hardware" for f in findings))
|
||||
|
||||
def test_clean_text_yields_no_findings(self):
|
||||
self.assertEqual(scan_journal_text("usb 1-1: new high-speed USB device\nbluetooth: ok"), [])
|
||||
|
||||
def test_run_health_checks_returns_findings(self):
|
||||
# Runs against the real system; just assert it returns a sorted list of Findings.
|
||||
findings = run_health_checks()
|
||||
self.assertIsInstance(findings, list)
|
||||
severities = [f.severity for f in findings]
|
||||
order = {"critical": 0, "warning": 1, "info": 2, "ok": 3}
|
||||
ranks = [order.get(s, 9) for s in severities]
|
||||
self.assertEqual(ranks, sorted(ranks))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user