Correlate private media delivery receipts

This commit is contained in:
jack
2026-07-25 23:49:41 +02:00
parent f355d66ed2
commit c5c6b7ca61
12 changed files with 710 additions and 34 deletions
@@ -89,7 +89,11 @@ private final class MockChatMediaTransferContext: ChatMediaTransferContext {
}
// Mesh file transfer
private(set) var privateFileSends: [(peerID: PeerID, transferId: String)] = []
private(set) var privateFileSends: [(
packet: BitchatFilePacket,
peerID: PeerID,
transferId: String
)] = []
private(set) var privateFileLegacyAllowances: [Bool] = []
private(set) var broadcastFileSends: [String] = []
private(set) var cancelledTransfers: [String] = []
@@ -154,7 +158,7 @@ private final class MockChatMediaTransferContext: ChatMediaTransferContext {
transferId: String,
allowLegacyFallback: Bool
) {
privateFileSends.append((peerID, transferId))
privateFileSends.append((packet, peerID, transferId))
privateFileLegacyAllowances.append(allowLegacyFallback)
}
@@ -172,19 +176,8 @@ private final class PausedVoiceNotePreparer: @unchecked Sendable {
private var started = false
private var released = false
private var finished = false
private let packet: BitchatFilePacket
init() {
let content = Data("voice".utf8)
packet = BitchatFilePacket(
fileName: "paused.m4a",
fileSize: UInt64(content.count),
mimeType: "audio/mp4",
content: content
)
}
func prepare(_: URL) throws -> BitchatFilePacket {
func prepare(_ url: URL) throws -> BitchatFilePacket {
condition.lock()
started = true
condition.broadcast()
@@ -194,7 +187,13 @@ private final class PausedVoiceNotePreparer: @unchecked Sendable {
finished = true
condition.broadcast()
condition.unlock()
return packet
let content = Data("voice".utf8)
return BitchatFilePacket(
fileName: url.lastPathComponent,
fileSize: UInt64(content.count),
mimeType: "audio/mp4",
content: content
)
}
var hasStarted: Bool {
@@ -452,6 +451,57 @@ struct ChatMediaTransferCoordinatorContextTests {
#expect(coordinator.transferIdToMessageIDs.isEmpty)
}
@Test @MainActor
func privateVoiceNoteUsesWireDerivableMessageID() async throws {
let context = MockChatMediaTransferContext()
let coordinator = ChatMediaTransferCoordinator(context: context)
let peerID = PeerID(str: "1122334455667788")
context.selectedPrivateChatPeer = peerID
let url = FileManager.default.temporaryDirectory
.appendingPathComponent("voice_receipt_\(UUID().uuidString).m4a")
try Data("voice".utf8).write(to: url)
defer { try? FileManager.default.removeItem(at: url) }
coordinator.sendVoiceNote(at: url)
#expect(await TestHelpers.waitUntil(
{ context.privateFileSends.count == 1 },
timeout: TestConstants.longTimeout
))
let message = try #require(context.privateChats[peerID]?.first)
let sentPacket = try #require(context.privateFileSends.first?.packet)
#expect(message.id == PrivateMediaMessageIdentity.stableID(
for: sentPacket,
senderPeerID: context.myPeerID,
recipientPeerID: peerID
))
}
@Test @MainActor
func privateImageUsesWireDerivableMessageID() async throws {
let context = MockChatMediaTransferContext()
let coordinator = ChatMediaTransferCoordinator(context: context)
let peerID = PeerID(str: "99aabbccddeeff00")
context.selectedPrivateChatPeer = peerID
let sourceURL = try makeCoordinatorTestImageURL()
defer { try? FileManager.default.removeItem(at: sourceURL) }
coordinator.sendImage(from: sourceURL)
#expect(await TestHelpers.waitUntil(
{ context.privateFileSends.count == 1 },
timeout: TestConstants.longTimeout
))
let message = try #require(context.privateChats[peerID]?.first)
let sentPacket = try #require(context.privateFileSends.first?.packet)
#expect(message.id == PrivateMediaMessageIdentity.stableID(
for: sentPacket,
senderPeerID: context.myPeerID,
recipientPeerID: peerID
))
coordinator.cleanupLocalFile(forMessage: message)
}
@Test @MainActor
func cancelVoiceNoteDuringDetachedPreparationCannotSendOrRestoreMapping() async throws {
let context = MockChatMediaTransferContext()