// // Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only // import XCTest @testable import SignalServiceKit final class TSOutgoingMessageRecipientStateTest: XCTestCase { func testStableDecoding() throws { struct TestCase { let data: Data let assertions: (TSOutgoingMessageRecipientState) -> Void } /// Data generated via `testGenerateData` below. let testCases: [TestCase] = [ TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a60b0c1718191a55246e756c6cd50d0e0f101112131414165624636c617373596572726f72436f64655573746174655f100f4d544c4d6f64656c56657273696f6e5b77617353656e7442795544800580038002800280041000100c08d21b1c1d1e5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a31f20215f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005a0060006b0072007c0082009400a000a200a400a600a800aa00ac00ae00af00b400bf00c800ea00ee011001190000000000000201000000000000002200000000000000000000000000000122")!, assertions: { state in XCTAssertEqual(state.status, .failed) XCTAssertEqual(state.errorCode, 12) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a60b0c1516171855246e756c6cd40d0e0f10111213145624636c6173735573746174655f100f4d544c4d6f64656c56657273696f6e5b77617353656e744279554480058003800280041000100108d2191a1b1c5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a31d1e1f5f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005a00600069007000760088009400960098009a009c009e00a000a100a600b100ba00dc00e00102010b0000000000000201000000000000002000000000000000000000000000000114")!, assertions: { state in XCTAssertEqual(state.status, .sending) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a60b0c1516171855246e756c6cd40d0e0f10111213145624636c6173735573746174655f100f4d544c4d6f64656c56657273696f6e5b77617353656e744279554480058003800280041000100208d2191a1b1c5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a31d1e1f5f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005a00600069007000760088009400960098009a009c009e00a000a100a600b100ba00dc00e00102010b0000000000000201000000000000002000000000000000000000000000000114")!, assertions: { state in XCTAssertEqual(state.status, .skipped) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a60b0c1516171855246e756c6cd40d0e0f10111213145624636c6173735573746174655f100f4d544c4d6f64656c56657273696f6e5b77617353656e744279554480058003800280041000100309d2191a1b1c5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a31d1e1f5f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005a00600069007000760088009400960098009a009c009e00a000a100a600b100ba00dc00e00102010b0000000000000201000000000000002000000000000000000000000000000114")!, assertions: { state in XCTAssertEqual(state.status, .sent) XCTAssertTrue(state.wasSentByUD) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a70b0c1718191a1b55246e756c6cd50d0e0f101112131415165624636c6173735573746174655f101164656c697665727954696d657374616d705f100f4d544c4d6f64656c56657273696f6e5b77617353656e74427955448006800380048002800510001003101709d21c1d1e1f5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a32021225f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005b0061006c00730079008d009f00ab00ad00af00b100b300b500b700b900bb00bc00c100cc00d500f700fb011d0126000000000000020100000000000000230000000000000000000000000000012f")!, assertions: { state in XCTAssertEqual(state.status, .delivered) XCTAssertEqual(state.statusTimestamp, 23) XCTAssertTrue(state.wasSentByUD) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a80b0c191a1b1c1d1e55246e756c6cd60d0e0f1011121314151617185d7265616454696d657374616d705624636c6173735573746174655f101164656c697665727954696d657374616d705f100f4d544c4d6f64656c56657273696f6e5b77617353656e7442795544800380078004800580028006100010171003101609d21f2021225a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a32324255f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005c0062006f007d0084008a009e00b000bc00be00c000c200c400c600c800ca00cc00ce00d000d100d600e100ea010c01100132013b0000000000000201000000000000002600000000000000000000000000000144")!, assertions: { state in XCTAssertEqual(state.status, .read) XCTAssertEqual(state.statusTimestamp, 23) XCTAssertTrue(state.wasSentByUD) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a90b0c1b1c1d1e1f202155246e756c6cd70d0e0f101112131415161718191a5624636c6173735f100f76696577656454696d657374616d705f100f4d544c4d6f64656c56657273696f6e5d7265616454696d657374616d705f101164656c697665727954696d657374616d705573746174655b77617353656e744279554480088006800280038005800480071000101610031015101709d2222324255a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a32627285f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005d006300720079008b009d00ab00bf00c500d100d300d500d700d900db00dd00df00e100e300e500e700e900ea00ef00fa010301250129014b0154000000000000020100000000000000290000000000000000000000000000015d")!, assertions: { state in XCTAssertEqual(state.status, .viewed) XCTAssertEqual(state.statusTimestamp, 23) XCTAssertTrue(state.wasSentByUD) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a80b0c191a1b1c1d1e55246e756c6cd60d0e0f1011121314151617185624636c6173735573746174655f101164656c697665727954696d657374616d705f100f4d544c4d6f64656c56657273696f6e5f100f76696577656454696d657374616d705b77617353656e7442795544800780038004800280058006100010031016101709d21f2021225a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a32324255f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005c0062006f0076007c009000a200b400c000c200c400c600c800ca00cc00ce00d000d200d400d500da00e500ee011001140136013f0000000000000201000000000000002600000000000000000000000000000148")!, assertions: { state in XCTAssertEqual(state.status, .viewed) XCTAssertEqual(state.statusTimestamp, 23) XCTAssertTrue(state.wasSentByUD) } ), TestCase( data: .data(fromHex: "62706c6973743030d4010203040506070a582476657273696f6e592461726368697665725424746f7058246f626a6563747312000186a05f100f4e534b657965644172636869766572d1080954726f6f748001a60b0c1516171855246e756c6cd40d0e0f10111213145624636c6173735573746174655f100f4d544c4d6f64656c56657273696f6e5b77617353656e744279554480058003800280041000100408d2191a1b1c5a24636c6173736e616d655824636c61737365735f101f54534f7574676f696e674d657373616765526563697069656e745374617465a31d1e1f5f101f54534f7574676f696e674d657373616765526563697069656e745374617465584d544c4d6f64656c584e534f626a65637400080011001a00240029003200370049004c00510053005a00600069007000760088009400960098009a009c009e00a000a100a600b100ba00dc00e00102010b0000000000000201000000000000002000000000000000000000000000000114")!, assertions: { state in XCTAssertEqual(state.status, .pending) } ), ] for (idx, testCase) in testCases.enumerated() { let state = try NSKeyedUnarchiver.unarchivedObject( ofClass: TSOutgoingMessageRecipientState.self, from: testCase.data, requiringSecureCoding: false ) guard let state else { XCTFail("Failed to decode test case \(idx)!") continue } testCase.assertions(state) } } /* /// Generate hex data for stable-decoding test fixtures. Preserved here for /// historical reference, but not expected to continue to compile as the /// model changes. func testGenerateData() { let states: [TSOutgoingMessageRecipientState] = [ { let state = TSOutgoingMessageRecipientState()! state.state = .failed state.errorCode = NSNumber(value: 12) return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sending return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .skipped return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sent state.wasSentByUD = true return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sent state.wasSentByUD = true state.deliveryTimestamp = NSNumber(value: 23) return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sent state.wasSentByUD = true state.deliveryTimestamp = NSNumber(value: 22) state.readTimestamp = NSNumber(value: 23) return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sent state.wasSentByUD = true state.deliveryTimestamp = NSNumber(value: 21) state.readTimestamp = NSNumber(value: 22) state.viewedTimestamp = NSNumber(value: 23) return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .sent state.wasSentByUD = true state.deliveryTimestamp = NSNumber(value: 22) state.viewedTimestamp = NSNumber(value: 23) return state }(), { let state = TSOutgoingMessageRecipientState()! state.state = .pending return state }(), ] for (idx, state) in states.enumerated() { let data = try! NSKeyedArchiver.archivedData( withRootObject: state, requiringSecureCoding: false ) print("\(idx): \(data.hexadecimalString)") } } */ }