import unittest

from h8536.analysis import build_call_graph
from h8536.data_analysis import analyze_unreached_data
from h8536.memory import region_for
from h8536.model import Instruction
from h8536.rom import Rom


class AnalysisOutputsTest(unittest.TestCase):
    def test_memory_regions_distinguish_ram_and_register_field(self):
        self.assertEqual(region_for(0xF680).name, "on_chip_ram")
        self.assertEqual(region_for(0xFE80).name, "register_field")
        self.assertEqual(region_for(0x0100).name, "program_or_external")

    def test_unreached_data_scan_finds_ascii_string_candidate(self):
        data = bytearray([0xFF] * 0x120)
        data[0x100:0x106] = b"HELLO!"

        candidates = analyze_unreached_data(Rom(bytes(data)), {}, 0, len(data))

        self.assertEqual(candidates["strings"][0]["address"], 0x100)
        self.assertEqual(candidates["strings"][0]["text"], "HELLO!")

    def test_call_graph_records_direct_calls_by_function_owner(self):
        instructions = {
            0x0100: Instruction(0x0100, b"\x18\x02\x00", "JSR", "@loc_0200", kind="call", targets=[0x0200]),
            0x0103: Instruction(0x0103, b"\x19", "RTS", kind="return", fallthrough=False),
            0x0200: Instruction(0x0200, b"\x19", "RTS", kind="return", fallthrough=False),
        }
        vectors = {0x0000: ("reset", 0x0100)}
        labels = {0x0100: "vec_reset_0100", 0x0200: "loc_0200"}

        graph = build_call_graph(instructions, vectors, labels)

        self.assertEqual(graph["edges"][0]["from"], 0x0100)
        self.assertEqual(graph["edges"][0]["to"], 0x0200)


if __name__ == "__main__":
    unittest.main()
