Files
bitchat/bitchatTests/Services/BLESubscriptionAnnounceLimiterTests.swift
193cfdc06a [codex] Extract BLE service policy helpers (#1321)
* Extract BLE service policy helpers

* Stabilize image media transfer test

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2026-06-01 14:16:44 +02:00

62 lines
2.3 KiB
Swift

import Foundation
import Testing
@testable import bitchat
@Suite("BLE subscription announce limiter tests")
struct BLESubscriptionAnnounceLimiterTests {
@Test("first subscription is allowed and repeated subscriptions are rate limited")
func repeatedSubscriptionsAreRateLimited() {
var limiter = BLESubscriptionAnnounceLimiter()
let centralID = "central-a"
let now = Date(timeIntervalSince1970: 100)
#expect(limiter.decision(for: centralID, now: now) == .allowed)
#expect(limiter.trackedCentralCount == 1)
let second = limiter.decision(for: centralID, now: now.addingTimeInterval(0.1))
#expect(second == .rateLimited(
backoffSeconds: TransportConfig.bleSubscriptionRateLimitMinSeconds,
attemptCount: 1,
suppressAnnounce: false
))
}
@Test("rapid subscription attempts eventually suppress announces")
func rapidAttemptsSuppressAnnouncesAtThreshold() {
var limiter = BLESubscriptionAnnounceLimiter()
let centralID = "central-a"
let now = Date(timeIntervalSince1970: 100)
#expect(limiter.decision(for: centralID, now: now) == .allowed)
var decision = BLESubscriptionAnnounceDecision.allowed
for attempt in 2...TransportConfig.bleSubscriptionRateLimitMaxAttempts {
decision = limiter.decision(
for: centralID,
now: now.addingTimeInterval(Double(attempt) * 0.01)
)
}
if case let .rateLimited(_, _, suppressAnnounce) = decision {
#expect(suppressAnnounce)
} else {
Issue.record("Expected rate-limited decision at suppression threshold")
}
}
@Test("stale limiter entries are pruned on the next decision")
func staleEntriesArePruned() {
var limiter = BLESubscriptionAnnounceLimiter()
let staleCentralID = "central-a"
let freshCentralID = "central-b"
let now = Date(timeIntervalSince1970: 100)
#expect(limiter.decision(for: staleCentralID, now: now) == .allowed)
#expect(limiter.trackedCentralCount == 1)
let afterWindow = now.addingTimeInterval(TransportConfig.bleSubscriptionRateLimitWindowSeconds + 1)
#expect(limiter.decision(for: freshCentralID, now: afterWindow) == .allowed)
#expect(limiter.trackedCentralCount == 1)
}
}