mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 22:45:19 +00:00
46 lines
2.7 KiB
Markdown
46 lines
2.7 KiB
Markdown
# Test Harness Guide
|
||
|
||
This test suite uses an in-memory networking harness to make end-to-end and integration tests deterministic, fast, and race-free without touching production code.
|
||
|
||
## In-Memory Bus
|
||
|
||
- **File:** `bitchatTests/Mocks/MockBLEService.swift`
|
||
- **Registry/Adjacency:** Global `registry` maps `peerID` to a `MockBLEService` instance; `adjacency` records simulated links between peers.
|
||
- **Setup:** Call `MockBLEService.resetTestBus()` in `setUp()` to clear state between tests.
|
||
- **Topology:** Use `simulateConnectedPeer(_:)` and `simulateDisconnectedPeer(_:)` to add/remove links. `connectFullMesh()` helpers in tests build larger topologies.
|
||
- **Handlers:** Tests can observe data via `messageDeliveryHandler` (decoded `BitchatMessage`) and `packetDeliveryHandler` (raw `BitchatPacket`).
|
||
- **De‑duplication:** A thread-safe `seenMessageIDs` prevents duplicate deliveries during flooding/relays.
|
||
|
||
## Broadcast Flooding
|
||
|
||
- **Flag:** `MockBLEService.autoFloodEnabled`
|
||
- **Intent:** When `true`, public broadcasts propagate across the entire connected component (ignores TTL for reach) while still de‑duping to prevent loops.
|
||
- **Usage:** Enabled in Integration tests (`setUp`) to simulate large-network broadcast; disabled in E2E tests to keep routing explicit and verify TTL behavior (see `PublicChatE2ETests.testZeroTTLNotRelayed`).
|
||
|
||
## Rehandshake Flow (Noise)
|
||
|
||
- **Why:** The legacy NACK recovery path was removed; recovery now relies on Noise session rehandshake after decrypt failure or desync.
|
||
- **Manager:** `NoiseSessionManager` manages per-peer sessions.
|
||
- **Pattern:** On decrypt failure, proactively clear the local session and re-initiate a handshake. The peer accepts and replaces their session.
|
||
- **Test:** `IntegrationTests.testRehandshakeAfterDecryptionFailure`
|
||
- Corrupts ciphertext to induce a decrypt error.
|
||
- Calls `removeSession(for:)` on the initiator’s manager before `initiateHandshake(with:)` to avoid `alreadyEstablished`.
|
||
- Verifies encrypt/decrypt succeeds post-rehandshake.
|
||
|
||
## Tips
|
||
|
||
- **Determinism:** Add small async delays only where handler installation/topology changes could race the first send.
|
||
- **Scoping:** Keep `autoFloodEnabled` toggled only within Integration tests; always reset in `tearDown()` to avoid cross-test contamination.
|
||
- **Direct vs Relay:** Private messages target a specific peer when adjacent; otherwise they are surfaced to neighbors for relay and, if known, also delivered to the target.
|
||
|
||
## Quick Start
|
||
|
||
- Create nodes and connect them:
|
||
- `let svc = MockBLEService(); svc.myPeerID = "PEER1"`
|
||
- `svc.simulateConnectedPeer("PEER2")`
|
||
- Observe messages:
|
||
- `svc.messageDeliveryHandler = { msg in /* asserts */ }`
|
||
- Enable broadcast flooding for Integration suites only:
|
||
- `MockBLEService.autoFloodEnabled = true`
|
||
|