// // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import LibSignalClient import XCTest @testable import SignalServiceKit final class OutgoingGroupCallUpdateMessageSerializationTest: SSKBaseTest { /// Confirms that an ``OutgoingGroupCallUpdateMessage`` (de)serializes. func testGroupCallUpdateMessageRoundTrip() throws { databaseStorage.write { tx in (DependenciesBridge.shared.registrationStateChangeManager as! RegistrationStateChangeManagerImpl).registerForTests( localIdentifiers: .init( aci: .init(fromUUID: UUID()), pni: .init(fromUUID: UUID()), e164: .init("+17735550199")! ), tx: tx.asV2Write ) } let updateMessage = write { tx in var groupModelBuilder = TSGroupModelBuilder() groupModelBuilder.name = "Test group" return OutgoingGroupCallUpdateMessage( thread: TSGroupThread(groupModel: try! groupModelBuilder.buildAsV2()), eraId: "beep boop", tx: tx ) } let archivedData = try NSKeyedArchiver.archivedData( withRootObject: updateMessage, requiringSecureCoding: false ) guard let deserializedMessage = try NSKeyedUnarchiver.unarchivedObject( ofClass: OutgoingGroupCallUpdateMessage.self, from: archivedData, requiringSecureCoding: false ) else { XCTFail("Failed to deserialize!") return } XCTAssertEqual(updateMessage, deserializedMessage) XCTAssertEqual(updateMessage.eraId, deserializedMessage.eraId) } /// Tests that an instance of this class that was serialized prior to the /// class' conversion to Swift still deserializes. /// /// This test contains a hardcoded representation of a serialized instance /// of this class from when it was ObjC. If this test fails, then data /// serialized on an old device may fail to deserialize. /// /// I believe the only place this could be serialized is in /// ``MessageSenderJobRecord``, which handles deserialization issues /// gracefully, but this test remains in case I'm wrong. func testObjcSerializedInstanceUnarchives() throws { let hardcodedObjcInstanceData: Data = try! .data(fromBase64Url: "YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGvEBkLDEdISUpLTE1RV2Bmam1xd3qBgoeMkJGSVSRudWxs3xAdDQ4PEBESExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKystListMTIrLSs2LTg5LSsrLSs_LSpCKy0rRl8QE3JlY2VpdmVkQXRUaW1lc3RhbXBfEBJpc1ZpZXdPbmNlQ29tcGxldGVfEBxzdG9yZWRTaG91bGRTdGFydEV4cGlyZVRpbWVyXxAPZXhwaXJlU3RhcnRlZEF0ViRjbGFzc18QEWlzVmlld09uY2VNZXNzYWdlXxAPTVRMTW9kZWxWZXJzaW9uXxAWcmVjaXBpZW50QWRkcmVzc1N0YXRlc151bmlxdWVUaHJlYWRJZF8QFWhhc0xlZ2FjeU1lc3NhZ2VTdGF0ZVZzb3J0SWRfEBJpc0Zyb21MaW5rZWREZXZpY2VVZXJhSWRfEBJsZWdhY3lNZXNzYWdlU3RhdGVfEBxvdXRnb2luZ01lc3NhZ2VTY2hlbWFWZXJzaW9uXxAQZ3JvdXBNZXRhTWVzc2FnZV8QEGV4cGlyZXNJblNlY29uZHNfEBJsZWdhY3lXYXNEZWxpdmVyZWReaXNWb2ljZU1lc3NhZ2VZZXhwaXJlc0F0XxARaXNHcm91cFN0b3J5UmVwbHldc2NoZW1hVmVyc2lvblllZGl0U3RhdGVZdGltZXN0YW1wWHVuaXF1ZUlkXxASd2FzUmVtb3RlbHlEZWxldGVkXxASc3RvcmVkTWVzc2FnZVN0YXRlXxATaGFzU3luY2VkVHJhbnNjcmlwdF1hdHRhY2htZW50SWRzgAaAA4ADgAKAGIADgAKACoAFgAOAAoADgASAAoASgBaAAoADgAOAAoADgBeAAoAGgAeAA4ACgAOACBAACFlib2JhIGZldHRfEBlna1hJOWFmWTkrVzRCUEZIU0JEWjhXQT09EwAAAYn12quGXxAkQzVBNjNERTUtOEZCOC00OUEzLTk1MDgtOTRBQzcyRERGMEI50k4RT1BaTlMub2JqZWN0c6CACdJSU1RVWiRjbGFzc25hbWVYJGNsYXNzZXNXTlNBcnJheaJUVlhOU09iamVjdNNYThFZXF9XTlMua2V5c6JaW4ALgA-iXV6AEYAUgBXTEWFiY2RlW2JhY2tpbmdVdWlkXxASYmFja2luZ1Bob25lTnVtYmVygA6ADIAA0mcRaGlcTlMudXVpZGJ5dGVzTxAQeOsX1A2qSdW57kKHFcmOvoAN0lJTa2xWTlNVVUlEomtW0lJTbm9fECVTaWduYWxTZXJ2aWNlS2l0LlNpZ25hbFNlcnZpY2VBZGRyZXNzonBWXxAlU2lnbmFsU2VydmljZUtpdC5TaWduYWxTZXJ2aWNlQWRkcmVzc9MRcnNjdWVbYmFja2luZ1V1aWRfEBJiYWNraW5nUGhvbmVOdW1iZXKADoAQgADSZxF4aU8QEMZolRAJIUBZgxS6bb5tEBWADdQRexN8fTgtK1VzdGF0ZVt3YXNTZW50QnlVRIATgBKAAoADEAHSUlODhF8QH1RTT3V0Z29pbmdNZXNzYWdlUmVjaXBpZW50U3RhdGWjhYZWXxAfVFNPdXRnb2luZ01lc3NhZ2VSZWNpcGllbnRTdGF0ZVhNVExNb2RlbNQRexN8fTgtK4ATgBKAAoAD0lJTjY5cTlNEaWN0aW9uYXJ5oo9WXE5TRGljdGlvbmFyeRADEATSUlOTlF8QG09XU091dGdvaW5nR3JvdXBDYWxsTWVzc2FnZaiVlpeYmZqGVl8QG09XU091dGdvaW5nR3JvdXBDYWxsTWVzc2FnZV8QEVRTT3V0Z29pbmdNZXNzYWdlWVRTTWVzc2FnZV1UU0ludGVyYWN0aW9uWUJhc2VNb2RlbF8QE1RTWWFwRGF0YWJhc2VPYmplY3QACAARABoAJAApADIANwBJAEwAUQBTAG8AdQCyAMgA3QD8AQ4BFQEpATsBVAFjAXsBggGXAZ0BsgHRAeQB9wIMAhsCJQI5AkcCUQJbAmQCeQKOAqQCsgK0ArYCuAK6ArwCvgLAAsICxALGAsgCygLMAs4C0ALSAtQC1gLYAtoC3ALeAuAC4gLkAuYC6ALqAuwC7gLvAvkDFQMeA0UDSgNVA1YDWANdA2gDcQN5A3wDhQOMA5QDlwOZA5sDngOgA6IDpAOrA7cDzAPOA9AD0gPXA-QD9wP5A_4EBQQIBA0ENQQ4BGAEZwRzBIgEigSMBI4EkwSmBKgEsQS3BMMExQTHBMkEywTNBNIE9AT4BRoFIwUsBS4FMAUyBTQFOQVGBUkFVgVYBVoFXwV9BYYFpAW4BcIF0AXaAAAAAAAAAgEAAAAAAAAAmwAAAAAAAAAAAAAAAAAABfA") guard let updateMessage = try NSKeyedUnarchiver.unarchivedObject( ofClass: OutgoingGroupCallUpdateMessage.self, from: hardcodedObjcInstanceData, requiringSecureCoding: false ) else { XCTFail("Failed to unarchive!") return } XCTAssertEqual(updateMessage.eraId, "boba fett") } }