4.8 KiB
Gate 2D: BLEPeerSessionManager Python Equivalence
Date: 2026-05-18 16:11 America/Los_Angeles
Scope: Python equivalence harness only. No live BLE integration.
Summary
Gate 2D added a Python test harness that compares current Python
BLEInterface._handle_identity_handshake behavior with the C++
BLEPeerSessionManager pybind decision/result model.
Added:
migration/tests/test_ble_peer_session_manager_python_equivalence.pymigration/phase2/Gate2D_BLEPeerSessionManager_python_equivalence_20260518_1611.mdmigration/sql/mark_gate2d_protocol_session_python_equivalence_20260518_1611.sql
Unchanged:
src/ble_reticulum/BLEInterface.py- live Python BLE behavior
- driver/platform code
- BlueZ/Bleak/DBus integration
RNS.Transportintegration- ESP32 BLE integration
Harness Design
The harness imports the real BLEInterface class, then binds these real Python methods onto a minimal fake object:
_handle_identity_handshake_check_duplicate_identity_compute_identity_hash_get_fragmenter_key
The fake object supplies only the state those methods require:
address_to_identityidentity_to_addressaddress_to_interfacespawned_interfacespeersfragmentersreassemblers_pending_identity_connections_pending_detach_last_real_data_zombie_timeout- fake driver
- fake fragmenter/reassembler constructors
- fake stale-address cleanup and spawn hooks
This avoids real RNS runtime, BlueZ, Bleak, DBus, and live BLE dependencies while still exercising the actual Python reference methods.
Equivalence Cases Covered
| Case | Python reference behavior checked | C++ result checked |
|---|---|---|
| non-16-byte payload | returns False |
PassToReassembler, consumed=false |
| new 16-byte identity | maps updated, fragmenter/reassembler created, pending removed, last-real-data updated, spawn requested | AcceptedNewIdentity, CreateFragmentationState, MarkPeerReady, RemovePendingIdentity, MarkRealData |
| known identity duplicate same | returns True, no normal data processing |
ConsumedDuplicateSameIdentity, consumed=true |
| known identity duplicate mismatch | returns True, warning recorded |
ConsumedDuplicateMismatchedIdentity, Warn, consumed=true |
| duplicate identity active elsewhere | disconnects current address | RejectedDuplicateIdentity, DisconnectCurrentPeer |
| duplicate identity with pending detach / stale old address | accepts new identity and invokes stale cleanup | AcceptedNewIdentity, CleanupOldAddress, UpdatePeerAddress |
| duplicate identity with zombie old connection | accepts new identity and disconnects old address | AcceptedNewIdentity, DisconnectOldPeer, CleanupOldAddress |
| MTU provided | fragmenter uses driver MTU | result MTU equals provided MTU |
| MTU missing | fragmenter falls back to 23 | result MTU equals 23 |
| pending identity removal | successful handshake removes pending address | RemovePendingIdentity |
| existing spawned interface path | existing peer address and address_to_interface update |
UpdatePeerAddress, MarkPeerReady |
| exception compatibility | Python consumes packet after synthetic MTU exception | skipped for C++; manager has no platform exception surface |
The skipped exception case is intentional documentation: current Python consumes after adapter-side exceptions, but the C++ session manager does not call platform dependencies such as driver.get_peer_mtu, so ErrorConsumed is not exercised cleanly at Gate 2D.
Verification
New Gate 2D test:
PYTHONPATH=migration/protocol_core pytest -q migration/tests/test_ble_peer_session_manager_python_equivalence.py
Result:
11 passed, 1 skipped, 2 warnings in 0.24s
Gate 2C / Gate 2D regression:
PYTHONPATH=migration/protocol_core pytest -q migration/tests/test_ble_peer_session_manager_pybind.py migration/tests/test_ble_peer_session_manager_python_equivalence.py
Result:
23 passed, 1 skipped, 2 warnings in 0.18s
Backend shim regression:
pytest -q migration/tests/test_fragmentation_backend_shim.py
Result:
9 passed, 2 warnings in 0.64s
Migration regression set:
PYTHONPATH=migration/protocol_core pytest -q migration/tests/test_fragmentation_cpp_equivalence.py migration/tests/test_identity_helpers_cpp_equivalence.py migration/tests/test_ble_peer_session_manager_pybind.py migration/tests/test_ble_peer_session_manager_python_equivalence.py
Result:
71 passed, 2 skipped, 2 warnings in 0.47s
SQL
Companion SQL:
migration/sql/mark_gate2d_protocol_session_python_equivalence_20260518_1611.sql
The SQL marks _handle_identity_handshake as PYTHON_EQUIVALENT for phase
2_ble_protocol_session_manager, keeps tag GLUE, keeps cpp_candidate=1, and does not mark any field-accepted status.