ble-reticulum/migration/phase2/Gate2D_BLEPeerSessionManager_python_equivalence_20260518_1611.md

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.py
  • migration/phase2/Gate2D_BLEPeerSessionManager_python_equivalence_20260518_1611.md
  • migration/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.Transport integration
  • 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_identity
  • identity_to_address
  • address_to_interface
  • spawned_interfaces
  • peers
  • fragmenters
  • reassemblers
  • _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.