"""Tests for the M5 system inventory (render + dict round-trip; collect on real system).""" import tempfile import unittest from pathlib import Path from rigdoctor.core import inventory from rigdoctor.core.inventory import Section class InventoryTests(unittest.TestCase): def test_collect_returns_sections(self): sections = inventory.collect() self.assertTrue(sections) titles = {s.title for s in sections} self.assertIn("System", titles) self.assertIn("CPU", titles) def test_dict_round_trip(self): sections = [Section("System", [("Kernel", "7.0.0"), ("Distro", "Ubuntu")])] restored = inventory.from_dict(inventory.to_dict(sections)) self.assertEqual(restored[0].title, "System") self.assertEqual(restored[0].items, [("Kernel", "7.0.0"), ("Distro", "Ubuntu")]) def test_render_markdown(self): md = inventory.render_markdown([Section("CPU", [("Model", "Test CPU")])]) self.assertIn("## CPU", md) self.assertIn("- **Model:** Test CPU", md) class PcieLinkTests(unittest.TestCase): def test_gen_mapping(self): self.assertEqual(inventory._gen("16.0 GT/s PCIe"), 4) self.assertEqual(inventory._gen("8.0 GT/s PCIe"), 3) self.assertIsNone(inventory._gen("")) def _fake_dev(self, cur_s, cur_w, max_s, max_w) -> Path: d = Path(tempfile.mkdtemp()) (d / "current_link_speed").write_text(cur_s) (d / "current_link_width").write_text(cur_w) (d / "max_link_speed").write_text(max_s) (d / "max_link_width").write_text(max_w) return d def test_link_at_full_speed(self): dev = self._fake_dev("16.0 GT/s PCIe", "4", "16.0 GT/s PCIe", "4") self.assertEqual(inventory._link_desc(dev), "PCIe Gen4 x4") def test_link_downtrained_flags_capability(self): dev = self._fake_dev("8.0 GT/s PCIe", "4", "16.0 GT/s PCIe", "4") self.assertEqual(inventory._link_desc(dev), "PCIe Gen3 x4 (capable of Gen4 x4)") def test_non_nvme_has_no_link(self): self.assertEqual(inventory._nvme_link("sda"), "") class MemorySpeedTests(unittest.TestCase): def test_rated_speed_from_part_number(self): self.assertEqual(inventory._rated_from_part("CMK32GX5M2B5600Z36"), 5600) self.assertEqual(inventory._rated_from_part("F5-6000J3038F16G"), 6000) self.assertIsNone(inventory._rated_from_part("NoSpeedHere")) def test_detects_unapplied_expo(self): # XMP/EXPO off: dmidecode only sees JEDEC 4800; the 5600 is in the part number. m = {"Configured Memory Speed": "4800 MT/s", "Speed": "4800 MT/s", "Part Number": "CMK32GX5M2B5600Z36"} self.assertEqual(inventory.module_speed(m), (4800, 5600)) def test_at_rated_speed(self): m = {"Configured Memory Speed": "5600 MT/s", "Speed": "5600 MT/s", "Part Number": "CMK32GX5M2B5600Z36"} self.assertEqual(inventory.module_speed(m), (5600, 5600)) if __name__ == "__main__": unittest.main()