mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 01:05:19 +00:00
P1: TorManager.shutdownCompletely() resets didStart asynchronously (after Arti has actually stopped, up to ~5s later). A brief offline->online flap could call startIfNeeded() inside that window; the guard on didStart dropped it, and nothing reevaluated afterwards, so Tor stayed down while activationAllowed was true. Track shutdowns in flight and record a deferred start, honored when the last shutdown finishes (still gated on allowAutoStart/foreground at that point). P2: NWPathReachabilityMonitor.ingest() cancelled and rescheduled the flush a full debounce interval from "now" on every observation, even duplicates (e.g. interface detail changes while still unsatisfied). ReachabilityDebounce already preserves the original pending.since, so schedule the flush for the remaining time to the true deadline instead of restarting the window. Tests: debounce deadline preservation (pure) + a monitor-level timing test that a mid-window duplicate does not postpone the offline commit. Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
jack
Claude Fable 5
parent
28ffc53f3f
commit
bbe5e1ef4e
@@ -57,6 +57,39 @@ final class NetworkReachabilityGateTests: XCTestCase {
|
||||
XCTAssertTrue(d.committed)
|
||||
}
|
||||
|
||||
func test_debounce_duplicateObservationsPreservePendingDeadline() {
|
||||
var d = ReachabilityDebounce(interval: 2.5, initial: true)
|
||||
let t0 = Date()
|
||||
XCTAssertNil(d.observe(reachable: false, at: t0))
|
||||
// Duplicate unsatisfied updates mid-window keep the original deadline.
|
||||
XCTAssertNil(d.observe(reachable: false, at: t0.addingTimeInterval(1.0)))
|
||||
XCTAssertEqual(d.pendingRemaining(at: t0.addingTimeInterval(1.0)), 1.5)
|
||||
// A duplicate arriving past the deadline commits immediately.
|
||||
XCTAssertEqual(d.observe(reachable: false, at: t0.addingTimeInterval(2.5)), false)
|
||||
XCTAssertNil(d.pendingRemaining(at: t0.addingTimeInterval(2.5)))
|
||||
}
|
||||
|
||||
func test_monitor_duplicateUpdatesDoNotPostponeOfflineCommit() async {
|
||||
let monitor = NWPathReachabilityMonitor(debounceInterval: 1.0)
|
||||
var received: [Bool] = []
|
||||
let cancellable = monitor.reachabilityPublisher.sink { received.append($0) }
|
||||
defer { cancellable.cancel() }
|
||||
|
||||
let start = Date()
|
||||
monitor.ingest(reachable: false)
|
||||
try? await Task.sleep(nanoseconds: 500_000_000)
|
||||
// Duplicate unsatisfied update mid-window (e.g. interface detail change
|
||||
// while still offline) must not restart the debounce window.
|
||||
monitor.ingest(reachable: false)
|
||||
|
||||
let committed = await waitUntil(timeout: 2.0) { !received.isEmpty }
|
||||
XCTAssertTrue(committed)
|
||||
XCTAssertEqual(received, [false])
|
||||
// The flush must fire at the original ~1.0s deadline, not ~1.5s
|
||||
// (a full interval after the duplicate).
|
||||
XCTAssertLessThan(Date().timeIntervalSince(start), 1.4)
|
||||
}
|
||||
|
||||
// MARK: - Service gating
|
||||
|
||||
func test_start_whenUnreachable_suppressesTorAndRelays() {
|
||||
|
||||
Reference in New Issue
Block a user