import unittest from h8536.emulator.bench_replay import ( BENCH_VISIBLE_C0_6020, CONNECT_OK_RESPONSE, assess_bench_parity, parse_bench_replay_log_text, ) SAMPLE_LOG = """\ CONNECT LCD bench sequence 21:44:28.062 TX 006 bytes 04 00 00 40 00 1E 21:44:28.215 TX 006 bytes 04 00 00 80 00 DE 21:44:28.218 RX 001 bytes 07 21:44:28.218 RX 002 bytes 80 C0 21:44:28.233 RX 001 bytes 60 21:44:28.234 RX 002 bytes 20 5D 21:44:29.149 RX 006 bytes 00 00 00 00 80 DA 21:44:36.078 SCREEN LCD after CONNECT sequence: CONNECT NOT ACT """ class EmulatorBenchReplayTest(unittest.TestCase): def test_parse_bench_log_extracts_tx_and_recombined_rx_frames(self): log = parse_bench_replay_log_text(SAMPLE_LOG) self.assertEqual([frame.frame.hex().upper() for frame in log.tx_frames], ["04000040001E", "0400008000DE"]) self.assertEqual(log.rx_frames[0].frame, BENCH_VISIBLE_C0_6020) self.assertEqual(log.rx_frames[0].label, "visible_C0_6020_family_candidate") self.assertEqual(log.screen_notes[-1].note, "CONNECT NOT ACT") def test_parity_flags_emulator_connect_ok_when_bench_stayed_not_active(self): log = parse_bench_replay_log_text(SAMPLE_LOG) parity = assess_bench_parity( log, emulator_tx_frames=[CONNECT_OK_RESPONSE], emulator_lcd_display=" CONNECT: OK | | | ", emulator_lcd_line_buffer=" CONNECT: OK ", ) self.assertFalse(parity["matched"]) self.assertIn("lcd_connect_state", parity["mismatch_reasons"]) self.assertIn("missing_visible_C0_6020_response", parity["mismatch_reasons"]) self.assertIn("emulator_emitted_connect_ok_response", parity["mismatch_reasons"]) def test_parity_passes_for_matching_not_active_visible_response(self): log = parse_bench_replay_log_text(SAMPLE_LOG) parity = assess_bench_parity( log, emulator_tx_frames=[BENCH_VISIBLE_C0_6020], emulator_lcd_display=" CONNECT:NOT ACT | | | ", emulator_lcd_line_buffer=" CONNECT:NOT ACT", ) self.assertTrue(parity["matched"]) if __name__ == "__main__": unittest.main()