traces
This commit is contained in:
@@ -77,6 +77,15 @@ class BenchConnectLcdTest(unittest.TestCase):
|
||||
def test_label_frame_marks_visible_retry_ack_target(self):
|
||||
self.assertEqual(label_frame(bytes.fromhex("07804020902D")), "visible_retry_0040_2090_candidate")
|
||||
|
||||
def test_label_frame_marks_active_selector0_keepalive_report(self):
|
||||
self.assertEqual(label_frame(bytes.fromhex("00000080805A")), "active_selector0_keepalive_report")
|
||||
|
||||
def test_label_frame_marks_copy_completion_exit_selector_006c_candidate(self):
|
||||
self.assertEqual(label_frame(bytes.fromhex("00006C000036")), "copy_completion_exit_selector_006c_candidate")
|
||||
|
||||
def test_label_frame_marks_copy_in_progress_selector_006d_candidate(self):
|
||||
self.assertEqual(label_frame(bytes.fromhex("00006D000037")), "copy_in_progress_selector_006d_candidate")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
33
tests/test_ccu_emulator.py
Normal file
33
tests/test_ccu_emulator.py
Normal file
@@ -0,0 +1,33 @@
|
||||
import unittest
|
||||
|
||||
from ccu_emulator.frames import ACTIVE_SEED_COMMAND0, NEUTRAL_ACK_FRAME, build_frame, frame_checksum_ok
|
||||
from ccu_emulator.policy import AckPolicy
|
||||
from ccu_emulator.refresh import PeriodicRefresh
|
||||
|
||||
|
||||
class CcuEmulatorFrameTests(unittest.TestCase):
|
||||
def test_build_frame_adds_checksum(self):
|
||||
self.assertEqual(build_frame(0x00, 0x0000, 0x8080), ACTIVE_SEED_COMMAND0)
|
||||
self.assertTrue(frame_checksum_ok(build_frame(0x06, 0x0015, 0x0001)))
|
||||
|
||||
def test_ack_policy_acknowledges_reports_with_neutral_ack(self):
|
||||
decision = AckPolicy().decide(bytes.fromhex("02000200005A"), "connect_ok_path_response_candidate")
|
||||
self.assertTrue(decision.should_ack)
|
||||
self.assertEqual(decision.frame, NEUTRAL_ACK_FRAME)
|
||||
|
||||
def test_ack_policy_skips_table_readback(self):
|
||||
decision = AckPolicy().decide(bytes.fromhex("04000080805E"), "table_readback_candidate")
|
||||
self.assertFalse(decision.should_ack)
|
||||
|
||||
|
||||
class PeriodicRefreshTests(unittest.TestCase):
|
||||
def test_periodic_refresh_returns_due_frames(self):
|
||||
refresh = PeriodicRefresh(frames=[ACTIVE_SEED_COMMAND0], interval=0.5)
|
||||
refresh.start(now=10.0)
|
||||
self.assertEqual(refresh.due_frames(now=10.4), [])
|
||||
self.assertEqual(refresh.due_frames(now=10.5), [ACTIVE_SEED_COMMAND0])
|
||||
self.assertEqual(refresh.due_frames(now=10.6), [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -191,6 +191,28 @@ class EmulatorHarnessTest(unittest.TestCase):
|
||||
self.assertEqual(writes[-1].value, 0x77)
|
||||
self.assertEqual(writes[-1].pc, 0x1000)
|
||||
|
||||
def test_panel_input_injection_sets_source_shadow_previous_and_dirty_edge(self):
|
||||
emulator = H8536Emulator(bytes(rom_with_reset()))
|
||||
|
||||
injection = emulator.inject_panel_input("cam-power", pressed=True)
|
||||
|
||||
self.assertEqual(injection.action.panel_input.selector, 0x0007)
|
||||
self.assertEqual(emulator.memory.read8(0xF105) & 0x08, 0x08)
|
||||
self.assertEqual(emulator.memory.read8(0xF6D4) & 0x08, 0x08)
|
||||
self.assertEqual(emulator.memory.read8(0xF6E4) & 0x08, 0x00)
|
||||
self.assertEqual(emulator.memory.read8(0xF6F2) & 0x10, 0x10)
|
||||
|
||||
def test_panel_input_release_forces_opposite_previous_sample(self):
|
||||
emulator = H8536Emulator(bytes(rom_with_reset()))
|
||||
|
||||
injection = emulator.inject_panel_input("call", pressed=False)
|
||||
|
||||
self.assertEqual(injection.action.panel_input.selector, 0x0015)
|
||||
self.assertEqual(emulator.memory.read8(0xF006) & 0x20, 0x00)
|
||||
self.assertEqual(emulator.memory.read8(0xF6DB) & 0x20, 0x00)
|
||||
self.assertEqual(emulator.memory.read8(0xF6EB) & 0x20, 0x20)
|
||||
self.assertEqual(emulator.memory.read8(0xF6F3) & 0x08, 0x08)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -2,7 +2,17 @@ import argparse
|
||||
import unittest
|
||||
|
||||
from h8536.emulator import H8536Emulator, SCI1_RDR, SCI1_SSR, SCI_SSR_ORER, SCI_SSR_RDRF
|
||||
from h8536.emulator.rx_probe import RunContext, UartTiming, _inject_frame_uart_timed, frame_checksum, frame_checksum_ok, parse_frame
|
||||
from h8536.emulator.rx_probe import (
|
||||
RunContext,
|
||||
UartTiming,
|
||||
_inject_frame_uart_timed,
|
||||
frame_checksum,
|
||||
frame_checksum_ok,
|
||||
parse_frame,
|
||||
parse_panel_action_arg,
|
||||
parse_panel_press_arg,
|
||||
parse_panel_release_arg,
|
||||
)
|
||||
|
||||
|
||||
def rom_with_reset(*, reset: int = 0x1000, size: int = 0x1020) -> bytearray:
|
||||
@@ -30,6 +40,25 @@ class EmulatorRxProbeTest(unittest.TestCase):
|
||||
with self.assertRaises(argparse.ArgumentTypeError):
|
||||
parse_frame("04 00 00 40")
|
||||
|
||||
def test_parse_panel_action_accepts_alias_state_and_raw_shadow_bit(self):
|
||||
action = parse_panel_action_arg("cam-power=release")
|
||||
self.assertEqual(action.panel_input.shadow, 0xF6D4)
|
||||
self.assertEqual(action.panel_input.bit, 3)
|
||||
self.assertFalse(action.pressed)
|
||||
|
||||
raw = parse_panel_press_arg("F6D4.6")
|
||||
self.assertEqual(raw.panel_input.source, 0xF105)
|
||||
self.assertEqual(raw.panel_input.dirty, 0xF6F2)
|
||||
self.assertEqual(raw.panel_input.dirty_bit, 4)
|
||||
self.assertTrue(raw.pressed)
|
||||
|
||||
def test_parse_panel_release_accepts_source_address_lane(self):
|
||||
action = parse_panel_release_arg("F006.5")
|
||||
|
||||
self.assertEqual(action.panel_input.shadow, 0xF6DB)
|
||||
self.assertEqual(action.panel_input.previous, 0xF6EB)
|
||||
self.assertFalse(action.pressed)
|
||||
|
||||
def test_uart_timed_injection_does_not_wait_for_rdrf_consumption(self):
|
||||
emulator = H8536Emulator(bytes(rom_with_reset()), clock_hz=10_000_000)
|
||||
context = RunContext()
|
||||
|
||||
37
tests/test_serial_scenario_compare.py
Normal file
37
tests/test_serial_scenario_compare.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import unittest
|
||||
|
||||
from h8536.serial_scenario_compare import format_comparison
|
||||
|
||||
|
||||
class SerialScenarioCompareTest(unittest.TestCase):
|
||||
def test_comparison_reports_extra_selector_and_value(self):
|
||||
baseline = {
|
||||
"_path": "baseline.json",
|
||||
"log": "baseline.txt",
|
||||
"rx_frames": 10,
|
||||
"ack_sent": 2,
|
||||
"ack_targets": {
|
||||
"01 00 02 00 00 59": 1,
|
||||
},
|
||||
}
|
||||
candidate = {
|
||||
"_path": "candidate.json",
|
||||
"log": "candidate.txt",
|
||||
"rx_frames": 12,
|
||||
"ack_sent": 3,
|
||||
"ack_targets": {
|
||||
"01 00 02 00 00 59": 1,
|
||||
"01 01 0F 80 00 D5": 1,
|
||||
},
|
||||
}
|
||||
|
||||
report = format_comparison(baseline, candidate)
|
||||
|
||||
self.assertIn("extra ACK-target frames in candidate", report)
|
||||
self.assertIn("01 01 0F 80 00 D5", report)
|
||||
self.assertIn("selector=0x008F", report)
|
||||
self.assertIn("value=0x8000", report)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user