mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 00:05:18 +00:00
Convert the remaining tests to Swift Testing (#781)
* SwiftTesting: NoiseProtocolTests + BinaryProtocolPaddingTests * SwiftTesting: `NotificationStreamAssemblerTests` * SwiftTesting: `NostrProtocolTests` * SwiftTesting: `BinaryProtocolTests` * SwiftTesting: `PeerIDTests` * SwiftTesting: `BLEServiceTests` * SwiftTesting: `CommandProcessorTests` * SwiftTesting: `GCSFilterTests` * SwiftTesting: `GeohashBookmarksStoreTests` * Remove `peerID` test constants * Remove PeerID + String interop from tests * Refactor IntegrationTests to extract state management * Refactor global state management of MockBLEService * NoiseProtocolSwiftTests: `actor` -> `struct` * Remove measurement tests w/ no benchmark * `NoiseProtocolSwiftTests` -> `NoiseProtocolTests` * SwiftTesting: `LocationChannelsTests` * SwiftTesting: `GossipSyncManagerTests` * SwiftTesting: `LocationNotesManagerTests` * Global `sleep` function for tests * SwiftTesting: `IntegrationTests` --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// MockBLEBus.swift
|
||||
// bitchatTests
|
||||
//
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// For more information, see <https://unlicense.org>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@testable import bitchat
|
||||
|
||||
final class MockBLEBus {
|
||||
private var registry: [PeerID: MockBLEService] = [:]
|
||||
private var adjacency: [PeerID: Set<PeerID>] = [:]
|
||||
|
||||
// Enable automatic flooding for public messages in integration tests only
|
||||
let autoFloodEnabled: Bool
|
||||
|
||||
init(autoFloodEnabled: Bool = false) {
|
||||
self.autoFloodEnabled = autoFloodEnabled
|
||||
}
|
||||
|
||||
func register(_ service: MockBLEService, for peerID: PeerID) {
|
||||
registry[peerID] = service
|
||||
if adjacency[peerID] == nil { adjacency[peerID] = [] }
|
||||
}
|
||||
|
||||
func connect(_ a: PeerID, _ b: PeerID) {
|
||||
var setA = adjacency[a] ?? []
|
||||
setA.insert(b)
|
||||
adjacency[a] = setA
|
||||
var setB = adjacency[b] ?? []
|
||||
setB.insert(a)
|
||||
adjacency[b] = setB
|
||||
}
|
||||
|
||||
func disconnect(_ a: PeerID, _ b: PeerID) {
|
||||
if var setA = adjacency[a] { setA.remove(b); adjacency[a] = setA }
|
||||
if var setB = adjacency[b] { setB.remove(a); adjacency[b] = setB }
|
||||
}
|
||||
|
||||
func neighbors(of peerID: PeerID) -> [MockBLEService] {
|
||||
let ids = adjacency[peerID] ?? []
|
||||
let result = ids.compactMap { registry[$0] }
|
||||
return result
|
||||
}
|
||||
|
||||
func isDirectNeighbor(_ a: PeerID, _ b: PeerID) -> Bool {
|
||||
let res = adjacency[a]?.contains(b) ?? false
|
||||
return res
|
||||
}
|
||||
|
||||
func service(for peerID: PeerID) -> MockBLEService? {
|
||||
let svc = registry[peerID]
|
||||
return svc
|
||||
}
|
||||
}
|
||||
@@ -26,13 +26,12 @@ import CoreBluetooth
|
||||
/// simulate broadcast propagation across the mesh. E2E tests keep it off and perform explicit
|
||||
/// relays when needed.
|
||||
final class MockBLEService: NSObject {
|
||||
// Enable automatic flooding for public messages in integration tests only
|
||||
static var autoFloodEnabled: Bool = false
|
||||
private let bus: MockBLEBus
|
||||
|
||||
// MARK: - Properties matching BLEService
|
||||
|
||||
weak var delegate: BitchatDelegate?
|
||||
var myPeerID: PeerID = "MOCK1234"
|
||||
var myPeerID = PeerID(str: "MOCK1234")
|
||||
var myNickname: String = "MockUser"
|
||||
|
||||
private let mockKeychain = MockKeychain()
|
||||
@@ -60,8 +59,8 @@ final class MockBLEService: NSObject {
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
init(bus: MockBLEBus) {
|
||||
self.bus = bus
|
||||
}
|
||||
|
||||
// MARK: - Methods matching BLEService
|
||||
@@ -71,42 +70,15 @@ final class MockBLEService: NSObject {
|
||||
}
|
||||
|
||||
// MARK: - In-memory test bus (for E2E/Integration)
|
||||
/// Global per-process bus for deterministic routing in tests.
|
||||
private static var registry: [PeerID: MockBLEService] = [:]
|
||||
private static var adjacency: [PeerID: Set<PeerID>] = [:]
|
||||
|
||||
/// Clears global bus state. Call from test `setUp()`.
|
||||
static func resetTestBus() {
|
||||
registry.removeAll()
|
||||
adjacency.removeAll()
|
||||
}
|
||||
|
||||
/// Registers this instance on first use.
|
||||
private func registerIfNeeded() {
|
||||
MockBLEService.registry[myPeerID] = self
|
||||
if MockBLEService.adjacency[myPeerID] == nil { MockBLEService.adjacency[myPeerID] = [] }
|
||||
bus.register(self, for: myPeerID)
|
||||
}
|
||||
|
||||
/// Returns adjacent neighbors based on the current simulated topology.
|
||||
private func neighbors() -> [MockBLEService] {
|
||||
guard let ids = MockBLEService.adjacency[myPeerID] else { return [] }
|
||||
return ids.compactMap { MockBLEService.registry[$0] }
|
||||
}
|
||||
|
||||
/// Adds an undirected edge between two peerIDs.
|
||||
private static func connectPeers(_ a: PeerID, _ b: PeerID) {
|
||||
var setA = adjacency[a] ?? []
|
||||
setA.insert(b)
|
||||
adjacency[a] = setA
|
||||
var setB = adjacency[b] ?? []
|
||||
setB.insert(a)
|
||||
adjacency[b] = setB
|
||||
}
|
||||
|
||||
/// Removes an undirected edge between two peerIDs.
|
||||
private static func disconnectPeers(_ a: PeerID, _ b: PeerID) {
|
||||
if var setA = adjacency[a] { setA.remove(b); adjacency[a] = setA }
|
||||
if var setB = adjacency[b] { setB.remove(a); adjacency[b] = setB }
|
||||
bus.neighbors(of: myPeerID)
|
||||
}
|
||||
|
||||
func startServices() {
|
||||
@@ -173,7 +145,7 @@ final class MockBLEService: NSObject {
|
||||
// Surface raw packet to tests that intercept/relay/encrypt
|
||||
packetDeliveryHandler?(packet)
|
||||
|
||||
// Deliver public messages to adjacent peers via test bus
|
||||
// Deliver public messages to adjacent peers via bus
|
||||
if recipientID == nil {
|
||||
for neighbor in neighbors() {
|
||||
neighbor.simulateIncomingPacket(packet)
|
||||
@@ -219,20 +191,16 @@ final class MockBLEService: NSObject {
|
||||
packetDeliveryHandler?(packet)
|
||||
|
||||
// If directly connected to recipient, deliver only to them.
|
||||
if let neighbors = MockBLEService.adjacency[myPeerID], neighbors.contains(recipientPeerID),
|
||||
let target = MockBLEService.registry[recipientPeerID] {
|
||||
if bus.isDirectNeighbor(myPeerID, recipientPeerID),
|
||||
let target = bus.service(for: recipientPeerID) {
|
||||
target.simulateIncomingPacket(packet)
|
||||
} else {
|
||||
// Not directly connected: deliver to neighbors for relay; also deliver directly if target is known
|
||||
if let target = MockBLEService.registry[recipientPeerID] {
|
||||
if let target = bus.service(for: recipientPeerID) {
|
||||
target.simulateIncomingPacket(packet)
|
||||
}
|
||||
if let neighbors = MockBLEService.adjacency[myPeerID] {
|
||||
for peer in neighbors where peer != recipientPeerID {
|
||||
if let neighbor = MockBLEService.registry[peer] {
|
||||
neighbor.simulateIncomingPacket(packet)
|
||||
}
|
||||
}
|
||||
for neighbor in neighbors() where neighbor.peerID != recipientPeerID {
|
||||
neighbor.simulateIncomingPacket(packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,14 +247,14 @@ final class MockBLEService: NSObject {
|
||||
|
||||
func simulateConnectedPeer(_ peerID: PeerID) {
|
||||
registerIfNeeded()
|
||||
MockBLEService.connectPeers(myPeerID, peerID)
|
||||
bus.connect(myPeerID, peerID)
|
||||
connectedPeers.insert(peerID)
|
||||
delegate?.didConnectToPeer(peerID)
|
||||
delegate?.didUpdatePeerList(Array(connectedPeers))
|
||||
}
|
||||
|
||||
func simulateDisconnectedPeer(_ peerID: PeerID) {
|
||||
MockBLEService.disconnectPeers(myPeerID, peerID)
|
||||
bus.disconnect(myPeerID, peerID)
|
||||
connectedPeers.remove(peerID)
|
||||
delegate?.didDisconnectFromPeer(peerID)
|
||||
delegate?.didUpdatePeerList(Array(connectedPeers))
|
||||
@@ -319,7 +287,7 @@ final class MockBLEService: NSObject {
|
||||
// When enabled, propagate a public broadcast across the entire connected
|
||||
// component regardless of the original TTL to better emulate large-network
|
||||
// broadcast expectations. De-duplication via seenMessageIDs prevents loops.
|
||||
if MockBLEService.autoFloodEnabled,
|
||||
if bus.autoFloodEnabled,
|
||||
packet.recipientID == nil,
|
||||
!message.isPrivate {
|
||||
let nextTTL = packet.ttl > 0 ? packet.ttl - 1 : 0
|
||||
@@ -353,8 +321,8 @@ typealias MockSimplifiedBluetoothService = MockBLEService
|
||||
// MARK: - Helpers
|
||||
|
||||
extension MockBLEService {
|
||||
convenience init(peerID: PeerID, nickname: String) {
|
||||
self.init()
|
||||
convenience init(peerID: PeerID, nickname: String, bus: MockBLEBus) {
|
||||
self.init(bus: bus)
|
||||
myPeerID = peerID
|
||||
mockNickname = nickname
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user