Signal-iOS/SignalServiceKit/tests/Messages/OWSOutgoingReceiptManagerTests.swift
Michelle Linington 1788e4a4fb Fixes a crash in OWSReceiptManager
Dictionary(uniqueKeysWithValues:) will assert that the provided keys are
unique and crash if a violation occurs. The existing code in
OWSReceiptManager falsely assumes that the addresses being built are
unique.

The keys in the key value store *are* unique, but as they're mapped into
addresses, we may have learned of a high trust e164/UUID mapping since
they were inserted. As the identifiers are mapped into
SignalServiceAddresses, the e164 and UUID are mapped to the same
SignalServiceAddress.

The fix is to just wrap our address builder in a Set() so we only have
one copy for each address.
2021-08-09 21:43:06 -03:00

71 lines
3.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
//
@testable import SignalServiceKit
import Foundation
import XCTest
class OWSOutgoingReceiptManagerTests: SSKBaseTestSwift, Dependencies {
func testMergeAddress() {
// Setup Store two different receipt sets for a uuid and an e164
let uuidAddress = SignalServiceAddress(uuid: UUID(), phoneNumber: nil, trustLevel: .low)
let uuidReceiptSet = MessageReceiptSet()
uuidReceiptSet.insert(timestamp: 1234, messageUniqueId: "uuid")
let e164Address = SignalServiceAddress(uuid: nil, phoneNumber: "+1234567890", trustLevel: .low)
let e164ReceiptSet = MessageReceiptSet()
e164ReceiptSet.insert(timestamp: 5678, messageUniqueId: "e164")
databaseStorage.write { writeTx in
outgoingReceiptManager.storeReceiptSet(uuidReceiptSet, type: .delivery, address: uuidAddress, transaction: writeTx)
outgoingReceiptManager.storeReceiptSet(e164ReceiptSet, type: .delivery, address: e164Address, transaction: writeTx)
}
// Test Fetch the receipt set for a merged address
let mergedAddress = SignalServiceAddress(uuid: uuidAddress.uuid!, phoneNumber: e164Address.phoneNumber!, trustLevel: .low)
let mergedReceipt = databaseStorage.read { readTx in
outgoingReceiptManager.fetchReceiptSet(type: .delivery, address: mergedAddress, transaction: readTx)
}
// Verify All timestamps exist in the merged receipt
XCTAssertTrue(mergedReceipt.timestamps.contains(1234))
XCTAssertTrue(mergedReceipt.timestamps.contains(5678))
XCTAssertTrue(mergedReceipt.uniqueIds.contains("uuid"))
XCTAssertTrue(mergedReceipt.uniqueIds.contains("e164"))
}
func testMergeAll() {
// Setup Store two different receipt sets for a uuid and an e164
let uuidAddress = SignalServiceAddress(uuid: UUID(), phoneNumber: nil, trustLevel: .low)
let uuidReceiptSet = MessageReceiptSet()
uuidReceiptSet.insert(timestamp: 1234, messageUniqueId: "uuid")
let e164Address = SignalServiceAddress(uuid: nil, phoneNumber: "+1234567890", trustLevel: .low)
let e164ReceiptSet = MessageReceiptSet()
e164ReceiptSet.insert(timestamp: 5678, messageUniqueId: "e164")
databaseStorage.write { writeTx in
outgoingReceiptManager.storeReceiptSet(uuidReceiptSet, type: .delivery, address: uuidAddress, transaction: writeTx)
outgoingReceiptManager.storeReceiptSet(e164ReceiptSet, type: .delivery, address: e164Address, transaction: writeTx)
}
// Test Mark the merged address as high trust, then fetch all receipt sets
let mergedAddress = SignalServiceAddress(uuid: uuidAddress.uuid!, phoneNumber: e164Address.phoneNumber!, trustLevel: .high)
let allReceipts = databaseStorage.read { readTx in
outgoingReceiptManager.fetchAllReceiptSets(type: .delivery, transaction: readTx)
}
// Verify The resulting dictionary contains one element. Maps the merged address to the merged receipt
XCTAssertEqual(allReceipts.count, 1)
XCTAssertEqual(allReceipts.keys.first, mergedAddress)
XCTAssertTrue(allReceipts.values.first!.timestamps.contains(1234))
XCTAssertTrue(allReceipts.values.first!.timestamps.contains(5678))
XCTAssertTrue(allReceipts.values.first!.uniqueIds.contains("uuid"))
XCTAssertTrue(allReceipts.values.first!.uniqueIds.contains("e164"))
}
}