Signal-iOS/Signal/test/util/ContactStreamTest.swift
2023-11-03 00:42:58 -05:00

233 lines
7.8 KiB
Swift

//
// Copyright 2019 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Contacts
import LibSignalClient
import XCTest
@testable import SignalMessaging
@testable import SignalServiceKit
class ContactStreamTest: SignalBaseTest {
// MARK: - Test Life Cycle
override func setUp() {
super.setUp()
Self.databaseStorage.write { tx in
(DependenciesBridge.shared.registrationStateChangeManager as! RegistrationStateChangeManagerImpl).registerForTests(
localIdentifiers: .forUnitTests,
tx: tx.asV2Write
)
}
}
// MARK: -
let outputContactSyncData = "GQoMKzEzMjMxMTExMTExEgdBbGljZS0xQAAxEgdBbGljZS0yQABKJDMxY2UxNDEyLTlhMjgtNGU2Zi1iNGVlLTIyMjIyMjIyMjIyMj8KDCsxMzIxMzMzMzMzMxIHQWxpY2UtM0AASiQxZDRhYjA0NS04OGZiLTRjNGUtOWY2YS0zMzMzMzMzMzMzMzM="
func test_writeContactSync() throws {
let signalAccounts = [
SignalAccount(address: SignalServiceAddress(phoneNumber: "+13231111111")),
SignalAccount(address: SignalServiceAddress(aciString: "31ce1412-9a28-4e6f-b4ee-222222222222")),
SignalAccount(address: SignalServiceAddress(aciString: "1d4ab045-88fb-4c4e-9f6a-333333333333", phoneNumber: "+13213333333"))
]
let streamData = try buildContactSyncData(signalAccounts: signalAccounts)
XCTAssertEqual(streamData.base64EncodedString(), outputContactSyncData)
}
func test_readContactSync() throws {
var contacts: [ContactDetails] = []
let data = Data(base64Encoded: outputContactSyncData)!
try data.withUnsafeBytes { bufferPtr in
if let baseAddress = bufferPtr.baseAddress, bufferPtr.count > 0 {
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
let inputStream = ChunkedInputStream(forReadingFrom: pointer, count: bufferPtr.count)
let contactStream = ContactsInputStream(inputStream: inputStream)
while let nextContact = try contactStream.decodeContact() {
contacts.append(nextContact)
}
}
}
guard contacts.count == 3 else {
XCTFail("unexpected contact count: \(contacts.count)")
return
}
do {
let contact = contacts[0]
XCTAssertEqual("+13231111111", contact.phoneNumber?.stringValue)
XCTAssertNil(contact.aci)
XCTAssertEqual(0, contact.expireTimer)
XCTAssertNil(contact.inboxSortOrder)
}
do {
let contact = contacts[1]
XCTAssertNil(contact.phoneNumber)
XCTAssertEqual("31CE1412-9A28-4E6F-B4EE-222222222222", contact.aci?.serviceIdUppercaseString)
XCTAssertEqual(0, contact.expireTimer)
XCTAssertNil(contact.inboxSortOrder)
}
do {
let contact = contacts[2]
XCTAssertEqual("+13213333333", contact.phoneNumber?.stringValue)
XCTAssertEqual("1D4AB045-88FB-4C4E-9F6A-333333333333", contact.aci?.serviceIdUppercaseString)
XCTAssertEqual(0, contact.expireTimer)
XCTAssertNil(contact.inboxSortOrder)
}
}
func buildContactSyncData(signalAccounts: [SignalAccount]) throws -> Data {
let contactsManager = TestContactsManager()
let dataOutputStream = OutputStream(toMemory: ())
dataOutputStream.open()
defer { dataOutputStream.close() }
let contactOutputStream = ContactOutputStream(outputStream: dataOutputStream)
for signalAccount in signalAccounts {
let contactFactory = ContactFactory()
contactFactory.fullNameBuilder = {
"Alice-\(signalAccount.recipientAddress.serviceIdentifier!.suffix(1))"
}
contactFactory.cnContactIdBuilder = { "123" }
contactFactory.uniqueIdBuilder = { "123" }
signalAccount.replaceContactForTests(try contactFactory.build())
try contactOutputStream.writeContact(
aci: signalAccount.recipientServiceId as? Aci,
phoneNumber: E164(signalAccount.recipientPhoneNumber),
signalAccount: signalAccount,
disappearingMessagesConfiguration: nil,
inboxPosition: nil,
isBlocked: false
)
}
return dataOutputStream.property(forKey: .dataWrittenToMemoryStreamKey) as! Data
}
}
class TestContactsManager: NSObject, ContactsManagerProtocol {
func fetchSignalAccount(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> SignalAccount? {
nil
}
func isSystemContactWithSignalAccount(_ address: SignalServiceAddress) -> Bool {
false
}
func isSystemContactWithSignalAccount(_ address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> Bool {
false
}
func hasNameInSystemContacts(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> Bool {
false
}
func comparableName(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> String {
self.displayName(for: address)
}
func comparableName(for signalAccount: SignalAccount, transaction: SDSAnyReadTransaction) -> String {
signalAccount.recipientAddress.stringForDisplay
}
func displayName(for address: SignalServiceAddress) -> String {
address.stringForDisplay
}
func displayName(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> String {
address.stringForDisplay
}
func displayName(for signalAccount: SignalAccount) -> String {
signalAccount.recipientAddress.stringForDisplay
}
func displayNames(forAddresses addresses: [SignalServiceAddress], transaction: SDSAnyReadTransaction) -> [String] {
return addresses.map {
$0.stringForDisplay
}
}
func displayName(for thread: TSThread, transaction: SDSAnyReadTransaction) -> String {
"Fake Name"
}
func displayNameWithSneakyTransaction(thread: TSThread) -> String {
"Fake Name"
}
func shortDisplayName(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> String {
address.stringForDisplay
}
func nameComponents(for address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> PersonNameComponents? {
PersonNameComponents()
}
func signalAccounts() -> [SignalAccount] {
[]
}
func isSystemContactWithSneakyTransaction(phoneNumber: String) -> Bool {
return true
}
func isSystemContact(phoneNumber: String, transaction: SDSAnyReadTransaction) -> Bool {
return true
}
func isSystemContactWithSneakyTransaction(address: SignalServiceAddress) -> Bool {
return true
}
func isSystemContact(address: SignalServiceAddress, transaction: SDSAnyReadTransaction) -> Bool {
return true
}
func isSystemContact(withSignalAccount phoneNumber: String) -> Bool {
true
}
func isSystemContact(withSignalAccount phoneNumber: String, transaction: SDSAnyReadTransaction) -> Bool {
true
}
func compare(signalAccount left: SignalAccount, with right: SignalAccount) -> ComparisonResult {
.orderedSame
}
public func sortSignalServiceAddresses(_ addresses: [SignalServiceAddress],
transaction: SDSAnyReadTransaction) -> [SignalServiceAddress] {
addresses
}
func cnContact(withId contactId: String?) -> CNContact? {
nil
}
func avatarData(forCNContactId contactId: String?) -> Data? {
nil
}
func avatarImage(forCNContactId contactId: String?) -> UIImage? {
nil
}
func leaseCacheSize(_ size: Int) -> ModelReadCacheSizeLease? {
return nil
}
var unknownUserLabel: String = "unknown"
}