// // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import LibSignalClient import XCTest @testable import SignalServiceKit class UserProfileMergerTest: XCTestCase { private var userProfileStore: MockUserProfileStore! private var userProfileMerger: UserProfileMerger! override func setUp() { super.setUp() userProfileStore = MockUserProfileStore() userProfileMerger = UserProfileMerger( userProfileStore: userProfileStore, setProfileKeyShim: { [userProfileStore] userProfile, profileKey, tx in userProfile.setValue(profileKey, forKey: "profileKey") userProfileStore!.updateUserProfile(userProfile, tx: tx) } ) } func testMergeLocal() { let aci = Aci.constantForTesting("00000000-0000-4000-8000-000000000aaa") let pni = Pni.constantForTesting("PNI:00000000-0000-4000-8000-000000000bbb") let phoneNumber = E164("+16505550100")! let localProfile = buildUserProfile(serviceId: nil, phoneNumber: OWSUserProfile.Constants.localProfilePhoneNumber, profileKey: nil) let otherProfile = buildUserProfile(serviceId: Aci.randomForTesting(), phoneNumber: nil, profileKey: nil) userProfileStore.userProfiles = [ localProfile, buildUserProfile(serviceId: aci, phoneNumber: nil, profileKey: Data(repeating: 1, count: 32)), buildUserProfile(serviceId: nil, phoneNumber: phoneNumber.stringValue, profileKey: Data(repeating: 2, count: 32)), buildUserProfile(serviceId: pni, phoneNumber: nil, profileKey: Data(repeating: 3, count: 32)), otherProfile ] MockDB().write { tx in userProfileMerger.didLearnAssociation( mergedRecipient: MergedRecipient( isLocalRecipient: true, oldRecipient: nil, newRecipient: SignalRecipient(aci: aci, pni: pni, phoneNumber: phoneNumber) ), tx: tx ) } XCTAssertEqual(userProfileStore.userProfiles, [localProfile, otherProfile]) } func testMergeOther() { let aci = Aci.constantForTesting("00000000-0000-4000-8000-000000000aaa") let pni = Pni.constantForTesting("PNI:00000000-0000-4000-8000-000000000bbb") let phoneNumber = E164("+16505550100")! let localProfile = buildUserProfile(serviceId: nil, phoneNumber: OWSUserProfile.Constants.localProfilePhoneNumber, profileKey: nil) let otherAciProfile = buildUserProfile(serviceId: Aci.randomForTesting(), phoneNumber: phoneNumber.stringValue, profileKey: nil) let otherPniProfile = buildUserProfile(serviceId: pni, phoneNumber: "+16505550101", profileKey: nil) let finalProfile = buildUserProfile(serviceId: aci, phoneNumber: nil, profileKey: nil) userProfileStore.userProfiles = [ localProfile, finalProfile, buildUserProfile(serviceId: aci, phoneNumber: phoneNumber.stringValue, profileKey: Data(repeating: 2, count: 32)), buildUserProfile(serviceId: nil, phoneNumber: phoneNumber.stringValue, profileKey: Data(repeating: 3, count: 32)), buildUserProfile(serviceId: pni, phoneNumber: phoneNumber.stringValue, profileKey: Data(repeating: 4, count: 32)), buildUserProfile(serviceId: pni, phoneNumber: nil, profileKey: Data(repeating: 5, count: 32)), otherAciProfile, otherPniProfile ] MockDB().write { tx in userProfileMerger.didLearnAssociation( mergedRecipient: MergedRecipient( isLocalRecipient: false, oldRecipient: nil, newRecipient: SignalRecipient(aci: aci, pni: pni, phoneNumber: phoneNumber) ), tx: tx ) } finalProfile.setValue(OWSAES256Key(data: Data(repeating: 2, count: 32))!, forKey: "profileKey") otherAciProfile.phoneNumber = nil otherPniProfile.serviceIdString = nil XCTAssertEqual(userProfileStore.userProfiles, [localProfile, finalProfile, otherAciProfile, otherPniProfile]) } private func buildUserProfile(serviceId: ServiceId?, phoneNumber: String?, profileKey: Data?) -> OWSUserProfile { return OWSUserProfile( id: nil, uniqueId: UUID().uuidString, serviceIdString: serviceId?.serviceIdUppercaseString, phoneNumber: phoneNumber, avatarFileName: nil, avatarUrlPath: nil, profileKey: profileKey.map { OWSAES256Key(data: $0)! }, givenName: nil, familyName: nil, bio: nil, bioEmoji: nil, badges: [], lastFetchDate: nil, lastMessagingDate: nil, isPhoneNumberShared: false ) } }