mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-10-18 07:33:46 +00:00
Merge e999d57c19abd0953762249532778926c3959ba1 into 9b84b361225facd8e623f25d76f889d3dc54a879
This commit is contained in:
commit
ef0183abfe
@ -29,6 +29,29 @@ final class SimulatedMesh {
|
||||
private var pendingDeliveries: [(from: Int, packet: BitchatPacket)] = []
|
||||
/// Total (packet, receiving-node) deliveries pumped — the storm bound.
|
||||
private(set) var deliveredFrameCount = 0
|
||||
/// The same deliveries split by packet type. A whole-mesh frame budget
|
||||
/// silently includes announce traffic, and announce *admission* is the one
|
||||
/// decision the manual scheduler does not own: `sendAnnounceNow` asks
|
||||
/// `announceThrottle.shouldSend(force:now: Date())` (BLEService), so
|
||||
/// whether a scheduled re-announce reaches the wire depends on real
|
||||
/// elapsed seconds, not on `advanceTime`. Burn 0.2s of wall clock in the
|
||||
/// middle of a test — the forced-announce window is 0.15s — and announce
|
||||
/// deliveries rise (measured: 22 → 36) while every other type is
|
||||
/// unchanged. A test that drains the mesh to quiet before it measures
|
||||
/// absorbs that into its baseline; one that cannot has a budget moving
|
||||
/// with runner load. Counting per type lets a test bound the traffic it
|
||||
/// is actually about either way.
|
||||
private var deliveredFrameCountsByType: [UInt8: Int] = [:]
|
||||
|
||||
/// Deliveries of one packet type — the storm bound for a specific kind of
|
||||
/// traffic, immune to unrelated announce frames.
|
||||
/// Unlocked deliberately, matching `deliveredFrameCount` above: both
|
||||
/// counters are written only by `pump` on the test thread (the outbound
|
||||
/// tap touches `pendingDeliveries`/`emitted`, never these). Taking the
|
||||
/// lock here would advertise a protection the writer does not hold.
|
||||
func deliveredFrameCount(ofType type: MessageType) -> Int {
|
||||
deliveredFrameCountsByType[type.rawValue] ?? 0
|
||||
}
|
||||
|
||||
private(set) var nodes: [Node] = []
|
||||
private var neighbors: [Set<Int>] = []
|
||||
@ -168,6 +191,7 @@ final class SimulatedMesh {
|
||||
for receiver in neighbors[from] {
|
||||
for link in links(from: from, at: receiver) {
|
||||
deliveredFrameCount += 1
|
||||
deliveredFrameCountsByType[packet.type, default: 0] += 1
|
||||
nodes[receiver].service._test_ingestFrame(packet, link: link)
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,7 +63,8 @@ struct SimulatedMeshTests {
|
||||
// baseline snapshot depends on the draw — the budget assertion below
|
||||
// flaked on CI at 14 and 18 frames for exactly that reason. Advance
|
||||
// until the mesh goes a full window with no new frames, so the
|
||||
// baseline only ever measures the message under test.
|
||||
// baseline only ever measures the message under test. Quiescence is
|
||||
// judged on every frame; the baseline itself is taken per type.
|
||||
var settled = mesh.deliveredFrameCount
|
||||
for _ in 0..<20 {
|
||||
mesh.advanceTime(by: 2)
|
||||
@ -71,7 +72,7 @@ struct SimulatedMeshTests {
|
||||
if now == settled { break }
|
||||
settled = now
|
||||
}
|
||||
let baseline = mesh.deliveredFrameCount
|
||||
let baseline = mesh.deliveredFrameCount(ofType: .message)
|
||||
|
||||
let capture = TransportEventCapture()
|
||||
c.service.eventDelegate = capture
|
||||
@ -84,9 +85,18 @@ struct SimulatedMeshTests {
|
||||
|
||||
let arrived = await capture.drainedPublicMessageCount(content: "hello line") == 1
|
||||
#expect(arrived)
|
||||
// Storm bound: a single public message across one relay hop must
|
||||
// not multiply into more than a handful of frames.
|
||||
#expect(mesh.deliveredFrameCount - baseline <= 12)
|
||||
// Storm bound: a single public message across one relay hop must not
|
||||
// multiply into more than a handful of frames. Counted per type so
|
||||
// the budget measures relay fan-out and nothing else. The whole-mesh
|
||||
// total also carries announces, and announce admission is the one
|
||||
// decision the manual scheduler does not own — `sendAnnounceNow` asks
|
||||
// `announceThrottle.shouldSend(force:now: Date())` — so announce
|
||||
// volume tracks real elapsed seconds. The settle loop above keeps
|
||||
// that traffic in the baseline rather than in the delta: burning 0.2s
|
||||
// of wall clock before it moves the baseline 66 → 80 frames and
|
||||
// leaves this delta at 4. Per-type counting is what makes the
|
||||
// assertion say which traffic it bounds.
|
||||
#expect(mesh.deliveredFrameCount(ofType: .message) - baseline <= 8)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user