hdcstorage / tests /test_x86.py
AEUPH's picture
HDCSTORAGE: hyperdimensional computer, webOS and agentic MCP layer (stdlib-only Python)
ad474c9 verified
Raw History Blame Contribute Delete
5.11 kB
import unittest
from hdc.x86 import BIOS, VIDEO_BASE, Boot, CPU, Halt, boot_sector
def load(cpu: CPU, code: list[int]) -> None:
for i, byte in enumerate(code):
cpu.write8(i, byte)
cpu.ip = 0
cpu.seg["CS"] = 0
class TestRegisters(unittest.TestCase):
def test_eight_bit_moves_hit_both_halves(self):
cpu = CPU()
load(cpu, [0xB8, 0x34, 0x12, 0xB4, 0x56]) # mov ax,1234h ; mov ah,56h
cpu.step()
self.assertEqual(cpu.r[0], 0x1234)
cpu.step()
self.assertEqual(cpu.al, 0x34)
self.assertEqual(cpu.ah, 0x56)
def test_mov_ds_from_ax(self):
cpu = CPU()
load(cpu, [0xB8, 0xC0, 0x07, 0x8E, 0xD8]) # mov ax,07C0h ; mov ds,ax
cpu.step()
cpu.step()
self.assertEqual(cpu.seg["DS"], 0x07C0)
def test_segment_offset_addressing(self):
cpu = CPU()
cpu.write8(cpu.physical(0x07C0, 0x18), ord("H"))
self.assertEqual(cpu.read8(cpu.physical(0x07C0, 0x18)), ord("H"))
class TestDisplacements(unittest.TestCase):
def test_short_jump_loops_in_place(self):
cpu = CPU()
load(cpu, [0xEB, 0xFE]) # jmp $
for _ in range(4):
cpu.step()
self.assertEqual(cpu.ip, 0)
def test_backwards_jump_lands_on_the_instruction(self):
cpu = CPU()
load(cpu, [0x90, 0xEB, 0xFD]) # nop ; jmp -3
cpu.step()
cpu.step()
self.assertEqual(cpu.ip, 0)
def test_conditional_jump_uses_the_flag(self):
cpu = CPU()
load(cpu, [0x31, 0xC0, 0x74, 0x02]) # xor ax,ax ; jz +2
cpu.step()
cpu.step()
self.assertEqual(cpu.ip, 6)
def test_taken_and_not_taken_paths(self):
cpu = CPU()
load(cpu, [0xB8, 0x01, 0x00, 0x74, 0x02]) # mov ax,1 ; jz +2
cpu.step()
cpu.step()
self.assertEqual(cpu.ip, 5) # not taken
class TestVideo(unittest.TestCase):
def test_teletype_writes_the_video_buffer(self):
cpu = CPU()
bios = BIOS(cpu)
bios.post()
cpu.ah, cpu.al = 0x0E, ord("A")
bios.video(cpu)
self.assertEqual(chr(cpu.read8(VIDEO_BASE)), "A")
def test_newline_moves_the_cursor(self):
cpu = CPU()
bios = BIOS(cpu)
bios.post()
bios.write("AB\r\nCD")
self.assertEqual(bios.screen()[0], "AB")
self.assertEqual(bios.screen()[1].rstrip(), "CD")
def test_long_line_wraps(self):
cpu = CPU()
bios = BIOS(cpu)
bios.post()
bios.write("X" * 81)
self.assertEqual(cpu.cursor, [1, 1])
def test_scrolling_keeps_the_latest_line(self):
cpu = CPU()
bios = BIOS(cpu)
bios.post()
for i in range(30):
bios.write("line %d\n" % i)
visible = [line for line in bios.screen() if line.strip()]
self.assertIn("line 29", visible[-1])
self.assertLessEqual(len(visible), 25)
class TestDisk(unittest.TestCase):
def test_bad_signature_raises(self):
cpu = CPU()
bios = BIOS(cpu, b"\x00" * 512)
bios.post()
with self.assertRaises(Halt):
bios.boot_attempt(cpu)
def test_read_sector_lands_at_es_bx(self):
cpu = CPU()
bios = BIOS(cpu, bytes(range(256)) * 2)
bios.post()
cpu.ah, cpu.al = 0x02, 1
cpu.r[1] = 0x0001 # CX: cylinder 0, sector 1
cpu.r[2] = 0x0000 # DX: head 0
cpu.seg["ES"] = 0x1000
cpu.r[3] = 0x0000 # BX
bios.read_sector(cpu)
self.assertEqual(cpu.read8(0x10000), 0)
self.assertEqual(cpu.read8(0x10001), 1)
self.assertFalse(cpu.flags & 0x0001)
def test_failed_read_sets_carry(self):
cpu = CPU()
bios = BIOS(cpu, b"")
bios.post()
cpu.ah = 0x02
bios.read_sector(cpu)
self.assertTrue(cpu.flags & 0x0001)
class TestBootChain(unittest.TestCase):
def test_sector_has_the_signature(self):
sector = boot_sector("hi")
self.assertEqual(len(sector), 512)
self.assertEqual(sector[510:512], b"\x55\xAA")
def test_boot_reaches_the_kernel_handoff(self):
machine = Boot()
machine.post()
result = machine.boot()
self.assertEqual(result["reason"], "kernel")
self.assertEqual(result["stage"], "kernel")
self.assertGreater(result["instructions"], 20)
def test_banner_is_written_to_video_memory(self):
machine = Boot("HELLO KERNEL")
machine.post()
machine.boot()
text = "\n".join(machine.screen())
self.assertIn("HELLO KERNEL", text)
self.assertIn("POST", text)
def test_ivt_is_populated(self):
machine = Boot()
machine.post()
self.assertNotEqual(machine.cpu.read16(0x10 * 4), 0)
self.assertNotEqual(machine.cpu.read16(0x10 * 4 + 2), 0)
def test_oversized_banner_is_rejected(self):
with self.assertRaises(ValueError):
boot_sector("x" * 600)
if __name__ == "__main__":
unittest.main()