// // CourierStoreTests.swift // bitchat // // This is free and unencumbered software released into the public domain. // For more information, see // import Testing import Foundation import BitFoundation @testable import bitchat struct CourierStoreTests { private static let baseDate = Date(timeIntervalSince1970: 1_750_000_000) private func makeStore(now: Date = baseDate) -> CourierStore { CourierStore(persistsToDisk: false, now: { now }) } /// Store whose clock can be advanced by tests. private final class Clock { var now: Date init(_ now: Date) { self.now = now } } private func makeEnvelope( recipientKey: Data = Data(repeating: 0xB0, count: 32), sealedAt: Date = baseDate, lifetime: TimeInterval = 60 * 60, ciphertext: Data = Data((0..<96).map { _ in UInt8.random(in: 0...255) }) ) -> CourierEnvelope { CourierEnvelope( recipientTag: CourierEnvelope.recipientTag( noiseStaticKey: recipientKey, epochDay: CourierEnvelope.epochDay(for: sealedAt) ), expiry: UInt64((sealedAt.timeIntervalSince1970 + lifetime) * 1000), ciphertext: ciphertext ) } private let depositorA = Data(repeating: 0xA1, count: 32) private let depositorB = Data(repeating: 0xA2, count: 32) // MARK: - Deposit and handover @Test func depositThenTakeForRecipient() { let store = makeStore() let recipientKey = Data(repeating: 0xB0, count: 32) let envelope = makeEnvelope(recipientKey: recipientKey) #expect(store.deposit(envelope, from: depositorA)) let taken = store.takeEnvelopes(for: recipientKey) #expect(taken == [envelope]) // Handover removes the envelope. #expect(store.takeEnvelopes(for: recipientKey).isEmpty) } @Test func takeIgnoresOtherRecipients() { let store = makeStore() let envelope = makeEnvelope(recipientKey: Data(repeating: 0xB0, count: 32)) store.deposit(envelope, from: depositorA) #expect(store.takeEnvelopes(for: Data(repeating: 0xCC, count: 32)).isEmpty) #expect(store.takeEnvelopes(for: Data(repeating: 0xB0, count: 32)).count == 1) } @Test func duplicateDepositIsIdempotent() { let store = makeStore() let recipientKey = Data(repeating: 0xB0, count: 32) let envelope = makeEnvelope(recipientKey: recipientKey) #expect(store.deposit(envelope, from: depositorA)) #expect(store.deposit(envelope, from: depositorA)) #expect(store.takeEnvelopes(for: recipientKey).count == 1) } // MARK: - Validity @Test func rejectsExpiredAndOversizedAndMalformed() { let store = makeStore() let expired = makeEnvelope(sealedAt: Self.baseDate.addingTimeInterval(-7200), lifetime: 3600) #expect(!store.deposit(expired, from: depositorA)) let oversized = makeEnvelope(ciphertext: Data(repeating: 0, count: CourierEnvelope.maxCiphertextBytes + 1)) #expect(!store.deposit(oversized, from: depositorA)) let badTag = CourierEnvelope( recipientTag: Data(repeating: 0, count: 4), expiry: UInt64((Self.baseDate.timeIntervalSince1970 + 3600) * 1000), ciphertext: Data(repeating: 1, count: 16) ) #expect(!store.deposit(badTag, from: depositorA)) } @Test func rejectsExpiryBeyondPolicyLifetime() { let store = makeStore() let pinned = makeEnvelope(lifetime: 7 * 24 * 60 * 60) #expect(!store.deposit(pinned, from: depositorA)) } // MARK: - Quotas @Test func perDepositorQuota() { let store = makeStore() for _ in 0..