mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-11-01 07:53:26 +00:00
Refactor BLEConnectTimeoutPolicy to use primitive attributes and eliminate CBPeripheral test mock crash
This commit is contained in:
parent
55d7cd460f
commit
929a86ce2b
@ -19,17 +19,18 @@ struct BLEPeripheralLinkState {
|
||||
}
|
||||
|
||||
struct BLEConnectTimeoutPolicy {
|
||||
/// Pure decision: given a captured attempt token and current link state,
|
||||
/// Pure decision: given a captured attempt token and current link state attributes,
|
||||
/// returns true if the timeout closure should act on this peripheral attempt.
|
||||
static func shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: UInt64,
|
||||
state: BLEPeripheralLinkState?,
|
||||
isConnecting: Bool,
|
||||
isConnected: Bool,
|
||||
currentAttemptToken: UInt64,
|
||||
isPeripheralConnected: Bool
|
||||
) -> Bool {
|
||||
guard let state = state else { return false }
|
||||
guard state.isConnecting && !state.isConnected else { return false }
|
||||
guard isConnecting && !isConnected else { return false }
|
||||
guard !isPeripheralConnected else { return false }
|
||||
guard state.attemptToken == capturedAttemptToken else { return false }
|
||||
guard currentAttemptToken == capturedAttemptToken else { return false }
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,11 +253,14 @@ final class BLERadioController {
|
||||
// this check, this now-stale timeout would cancel that newer,
|
||||
// still-live attempt out from under it and apply a
|
||||
// connection-timeout penalty to a peer that never actually timed out.
|
||||
guard BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: attemptToken,
|
||||
state: state,
|
||||
isPeripheralConnected: peripheral.state == .connected
|
||||
) else {
|
||||
guard let state,
|
||||
BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: attemptToken,
|
||||
isConnecting: state.isConnecting,
|
||||
isConnected: state.isConnected,
|
||||
currentAttemptToken: state.attemptToken,
|
||||
isPeripheralConnected: peripheral.state == .connected
|
||||
) else {
|
||||
if let state, state.attemptToken != attemptToken {
|
||||
SecureLogger.debug("⏱️ Timeout fired for a superseded connection attempt, ignoring: \(candidate.name)", category: .session)
|
||||
}
|
||||
|
||||
@ -1,39 +1,18 @@
|
||||
import Foundation
|
||||
import CoreBluetooth
|
||||
import Testing
|
||||
@testable import bitchat
|
||||
|
||||
struct BLEConnectTimeoutPolicyTests {
|
||||
@Test
|
||||
func validConnectingAttemptTriggersTimeout() {
|
||||
let token: UInt64 = 42
|
||||
|
||||
// When state is nil -> false
|
||||
#expect(!BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: token,
|
||||
state: nil,
|
||||
isPeripheralConnected: false
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
func supersededAttemptTokenIgnoresTimeout() {
|
||||
let capturedToken: UInt64 = 1
|
||||
let currentToken: UInt64 = 2
|
||||
|
||||
let mockState = BLEPeripheralLinkState(
|
||||
peripheral: CBPeripheralMock.create(),
|
||||
characteristic: nil,
|
||||
isConnecting: true,
|
||||
isConnected: false,
|
||||
lastConnectionAttempt: Date(),
|
||||
attemptToken: currentToken,
|
||||
assembler: NotificationStreamAssembler()
|
||||
)
|
||||
|
||||
let result = BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: capturedToken,
|
||||
state: mockState,
|
||||
isConnecting: true,
|
||||
isConnected: false,
|
||||
currentAttemptToken: currentToken,
|
||||
isPeripheralConnected: false
|
||||
)
|
||||
|
||||
@ -44,19 +23,11 @@ struct BLEConnectTimeoutPolicyTests {
|
||||
func matchingAttemptTokenExecutesTimeout() {
|
||||
let token: UInt64 = 5
|
||||
|
||||
let mockState = BLEPeripheralLinkState(
|
||||
peripheral: CBPeripheralMock.create(),
|
||||
characteristic: nil,
|
||||
isConnecting: true,
|
||||
isConnected: false,
|
||||
lastConnectionAttempt: Date(),
|
||||
attemptToken: token,
|
||||
assembler: NotificationStreamAssembler()
|
||||
)
|
||||
|
||||
let result = BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: token,
|
||||
state: mockState,
|
||||
isConnecting: true,
|
||||
isConnected: false,
|
||||
currentAttemptToken: token,
|
||||
isPeripheralConnected: false
|
||||
)
|
||||
|
||||
@ -67,31 +38,29 @@ struct BLEConnectTimeoutPolicyTests {
|
||||
func connectedStateIgnoresTimeout() {
|
||||
let token: UInt64 = 5
|
||||
|
||||
let mockState = BLEPeripheralLinkState(
|
||||
peripheral: CBPeripheralMock.create(),
|
||||
characteristic: nil,
|
||||
let result = BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: token,
|
||||
isConnecting: false,
|
||||
isConnected: true,
|
||||
lastConnectionAttempt: Date(),
|
||||
attemptToken: token,
|
||||
assembler: NotificationStreamAssembler()
|
||||
currentAttemptToken: token,
|
||||
isPeripheralConnected: true
|
||||
)
|
||||
|
||||
#expect(!result)
|
||||
}
|
||||
|
||||
@Test
|
||||
func peripheralConnectedStateIgnoresTimeout() {
|
||||
let token: UInt64 = 5
|
||||
|
||||
let result = BLEConnectTimeoutPolicy.shouldExecuteConnectTimeout(
|
||||
capturedAttemptToken: token,
|
||||
state: mockState,
|
||||
isConnecting: true,
|
||||
isConnected: false,
|
||||
currentAttemptToken: token,
|
||||
isPeripheralConnected: true
|
||||
)
|
||||
|
||||
#expect(!result)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper mock CBPeripheral for tests
|
||||
private final class CBPeripheralMock {
|
||||
static func create() -> CBPeripheral {
|
||||
let dummy = UnsafeMutableRawPointer.allocate(byteCount: 256, alignment: 16)
|
||||
dummy.initializeMemory(as: UInt8.self, repeating: 0, count: 256)
|
||||
return Unmanaged<CBPeripheral>.fromOpaque(dummy).takeUnretainedValue()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user