"""Tests for the .dmp minidump parser (M14) — builds a synthetic MDMP, no external tools.""" import struct import tempfile import unittest from pathlib import Path from unittest import mock from rigdoctor.core import minidump def _synthetic_dump() -> bytes: """A minimal but valid MDMP: header + SystemInfo + Exception + 2-module ModuleList. Layout (absolute file offsets): header@0, directory@32, SystemInfo@68, Exception@96, ModuleList@264, name strings@484. Module0 spans the exception address, so it's faulting. """ buf = bytearray(600) struct.pack_into("<4sIIIIIQ", buf, 0, b"MDMP", 0xA793, 3, 32, 0, 1_700_000_000, 0) struct.pack_into("` parses then explains via the configured provider.""" def _args(self, **over): import argparse base = {"ai_cmd": "dump", "file": ""} base.update(over) return argparse.Namespace(**base) def test_dump_parses_and_explains(self): from rigdoctor.core import ai with tempfile.NamedTemporaryFile(suffix=".dmp", delete=False) as fh: fh.write(_synthetic_dump()) path = fh.name try: with mock.patch.object(ai, "is_configured", return_value=True), \ mock.patch.object(ai, "provider_label", return_value="Claude (test)"), \ mock.patch.object(minidump, "stackwalk", return_value=""), \ mock.patch.object(ai, "explain", return_value=(True, "Likely DXVK.")) as explain: from rigdoctor import cli rc = cli.cmd_ai(self._args(file=path)) finally: Path(path).unlink(missing_ok=True) self.assertEqual(rc, 0) sent = explain.call_args[0][0] self.assertIn("Proton", sent) # the Linux/Proton framing reached the model self.assertIn("game.exe", sent) def test_dump_bad_file_returns_error(self): from rigdoctor.core import ai with mock.patch.object(ai, "is_configured", return_value=True): from rigdoctor import cli rc = cli.cmd_ai(self._args(file="/nope/missing.dmp")) self.assertEqual(rc, 1) if __name__ == "__main__": unittest.main()