EEPROM layout
This commit is contained in:
120
tests/test_eeprom_layout.py
Normal file
120
tests/test_eeprom_layout.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import io
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from h8536.eeprom_layout import (
|
||||
analyze_eeprom_layout,
|
||||
format_text_report,
|
||||
main,
|
||||
write_eeprom_layout,
|
||||
)
|
||||
|
||||
|
||||
def reference(address: int) -> dict:
|
||||
return {"address": address}
|
||||
|
||||
|
||||
def instruction(address: int, mnemonic: str, operands: str = "", refs: list[int] | None = None) -> dict:
|
||||
return {
|
||||
"address": address,
|
||||
"mnemonic": mnemonic,
|
||||
"operands": operands,
|
||||
"text": f"{mnemonic} {operands}".strip(),
|
||||
"references": [reference(item) for item in (refs or [])],
|
||||
"targets": [],
|
||||
}
|
||||
|
||||
|
||||
def payload() -> dict:
|
||||
return {
|
||||
"instructions": [
|
||||
instruction(0x410C, "MOV:G.W", "R5, @(-H'0C00,R0)"),
|
||||
instruction(0x41E8, "MOV:G.W", "R5, @(-H'0850,R1)"),
|
||||
instruction(0x40FA, "CMP:G.W", "#H'6B6F, @H'F402", [0xF402]),
|
||||
instruction(0xBD3D, "MOV:G.B", "@(-H'3A9B,R4), R1"),
|
||||
instruction(0xBD45, "MOV:G.W", "R0, @(-H'0C00,R1)"),
|
||||
instruction(0xBD49, "BTST.B", "#7, @H'F76E", [0xF76E]),
|
||||
],
|
||||
"call_graph": {
|
||||
"nodes": [
|
||||
{"start": 0x4000, "end": 0x4216, "label": "loc_4000"},
|
||||
{"start": 0xBD0E, "end": 0xBD67, "label": "loc_BD0E"},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def rom_bytes() -> bytes:
|
||||
rom = bytearray([0xFF] * 0xCB00)
|
||||
rom[0xC564 : 0xC564 + 0x400] = b"\x00" * 0x400
|
||||
rom[0xC564 + 0x015 * 2 : 0xC564 + 0x015 * 2 + 2] = b"\x40\xAA"
|
||||
rom[0xC966:0xC968] = b"\x6B\x6F"
|
||||
rom[0xC968:0xC96A] = b"\xFE\x00"
|
||||
rom[0xCA0E:0xCA10] = b"\x80\x00"
|
||||
return bytes(rom)
|
||||
|
||||
|
||||
class EepromLayoutTest(unittest.TestCase):
|
||||
def test_analysis_extracts_factory_defaults_records_and_selector_mapping(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
rom_path = Path(tmp) / "rom.bin"
|
||||
rom_path.write_bytes(rom_bytes())
|
||||
|
||||
analysis = analyze_eeprom_layout(payload(), rom_path=rom_path)
|
||||
|
||||
self.assertEqual(analysis["kind"], "eeprom_layout")
|
||||
self.assertEqual(analysis["factory_defaults"]["entries"][1]["factory_word_hex"], "0x6B6F")
|
||||
self.assertEqual(analysis["persistent_records"][3]["ram_base_hex"], "H'F7C8")
|
||||
self.assertEqual(analysis["persistent_records"][3]["eeprom_base_hex"], "0x300")
|
||||
mapped = analysis["serial_persistence_mapping"]["entries"][0]
|
||||
self.assertEqual(mapped["selector_hex"], "0x015")
|
||||
self.assertEqual(mapped["shadow_address_hex"], "H'F4AA")
|
||||
self.assertEqual(mapped["eeprom_word_offset_hex"], "0xAA")
|
||||
self.assertEqual(mapped["factory_word_hex"], "0x8000")
|
||||
|
||||
def test_text_report_mentions_core_layout(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
rom_path = Path(tmp) / "rom.bin"
|
||||
rom_path.write_bytes(rom_bytes())
|
||||
analysis = analyze_eeprom_layout(payload(), rom_path=rom_path)
|
||||
|
||||
text = format_text_report(analysis)
|
||||
|
||||
self.assertIn("Persistent 8-Byte Records", text)
|
||||
self.assertIn("selector 0x015", text)
|
||||
self.assertIn("F76E", text)
|
||||
|
||||
def test_write_json_output(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
input_path = Path(tmp) / "rom.json"
|
||||
output_path = Path(tmp) / "eeprom.json"
|
||||
rom_path = Path(tmp) / "rom.bin"
|
||||
input_path.write_text(json.dumps(payload()), encoding="utf-8")
|
||||
rom_path.write_bytes(rom_bytes())
|
||||
|
||||
write_eeprom_layout(input_path, output_path, rom_path=rom_path, as_json=True)
|
||||
|
||||
written = json.loads(output_path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(written["kind"], "eeprom_layout")
|
||||
self.assertEqual(written["summary"]["persistent_record_count"], 16)
|
||||
|
||||
def test_cli_writes_text_report(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
input_path = Path(tmp) / "rom.json"
|
||||
output_path = Path(tmp) / "eeprom.txt"
|
||||
rom_path = Path(tmp) / "rom.bin"
|
||||
input_path.write_text(json.dumps(payload()), encoding="utf-8")
|
||||
rom_path.write_bytes(rom_bytes())
|
||||
|
||||
stdout = io.StringIO()
|
||||
rc = main([str(input_path), "--rom", str(rom_path), "--out", str(output_path)], stdout=stdout)
|
||||
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertIn("wrote", stdout.getvalue())
|
||||
self.assertIn("EEPROM Layout Report", output_path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user