// // Copyright (c) 2021 Open Whisper Systems. All rights reserved. // #import "SSKBaseTestObjC.h" #import "TSAccountManager.h" #import "TSContactThread.h" #import "TSGroupThread.h" #import "TSIncomingMessage.h" #import "TSMessage.h" #import "TSOutgoingMessage.h" #import "TSThread.h" #import #import @interface TSMessageStorageTests : SSKBaseTestObjC @property TSContactThread *thread; @end #pragma mark - @implementation TSMessageStorageTests - (SignalServiceAddress *)localAddress { return [[SignalServiceAddress alloc] initWithPhoneNumber:@"+13334445555"]; } - (SignalServiceAddress *)otherAddress { return [[SignalServiceAddress alloc] initWithPhoneNumber:@"+12223334444"]; } - (void)setUp { [super setUp]; // ensure local client has necessary "registered" state NSString *localE164Identifier = @"+13235551234"; NSUUID *localUUID = NSUUID.UUID; [self.tsAccountManager registerForTestsWithLocalNumber:localE164Identifier uuid:localUUID]; [self writeWithBlock:^(SDSAnyWriteTransaction *transaction) { self.thread = [TSContactThread getOrCreateThreadWithContactAddress:self.otherAddress transaction:transaction]; }]; } - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } - (void)testStoreIncomingMessage { __block NSString *messageId; uint64_t timestamp = 666; NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to " @"have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because " @"privacy matters; privacy is what allows us to determine who we are and who we want to be."; [self writeWithBlock:^(SDSAnyWriteTransaction *transaction) { TSIncomingMessageBuilder *incomingMessageBuilder = [TSIncomingMessageBuilder incomingMessageBuilderWithThread:self.thread messageBody:body]; incomingMessageBuilder.timestamp = timestamp; incomingMessageBuilder.authorAddress = self.otherAddress; incomingMessageBuilder.sourceDeviceId = 1; TSIncomingMessage *newMessage = [incomingMessageBuilder build]; [newMessage anyInsertWithTransaction:transaction]; messageId = newMessage.uniqueId; TSIncomingMessage *_Nullable fetchedMessage = [TSIncomingMessage anyFetchIncomingMessageWithUniqueId:messageId transaction:transaction]; XCTAssertEqualObjects(body, fetchedMessage.body); XCTAssertFalse(fetchedMessage.hasAttachments); XCTAssertEqual(timestamp, fetchedMessage.timestamp); XCTAssertFalse(fetchedMessage.wasRead); XCTAssertEqualObjects(self.thread.uniqueId, fetchedMessage.uniqueThreadId); }]; } - (void)testMessagesDeletedOnThreadDeletion { NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to " @"have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because " @"privacy matters; privacy is what allows us to determine who we are and who we want to be."; [self writeWithBlock:^(SDSAnyWriteTransaction *transaction) { NSMutableArray *messages = [NSMutableArray new]; for (int i = 0; i < 10; i++) { TSIncomingMessageBuilder *incomingMessageBuilder = [TSIncomingMessageBuilder incomingMessageBuilderWithThread:self.thread messageBody:body]; incomingMessageBuilder.timestamp = i + 1; incomingMessageBuilder.authorAddress = self.otherAddress; incomingMessageBuilder.sourceDeviceId = 1; TSIncomingMessage *newMessage = [incomingMessageBuilder build]; [messages addObject:newMessage]; [newMessage anyInsertWithTransaction:transaction]; } for (TSIncomingMessage *message in messages) { TSIncomingMessage *_Nullable fetchedMessage = [TSIncomingMessage anyFetchIncomingMessageWithUniqueId:message.uniqueId transaction:transaction]; XCTAssertEqualObjects(fetchedMessage.body, body, @"Body of incoming message recovered"); XCTAssertEqual(0, fetchedMessage.attachmentIds.count, @"attachments are nil"); XCTAssertEqualObjects(fetchedMessage.uniqueId, message.uniqueId, @"Unique identifier is accurate"); XCTAssertFalse(fetchedMessage.wasRead, @"Message should originally be unread"); XCTAssertEqualObjects( fetchedMessage.uniqueThreadId, self.thread.uniqueId, @"Isn't stored in the right thread!"); } [self.thread anyRemoveWithTransaction:transaction]; for (TSIncomingMessage *message in messages) { TSIncomingMessage *_Nullable fetchedMessage = [TSIncomingMessage anyFetchIncomingMessageWithUniqueId:message.uniqueId transaction:transaction]; XCTAssertNil(fetchedMessage, @"Message should be deleted!"); } }]; } - (void)testGroupMessagesDeletedOnThreadDeletion { NSString *body = @"A child born today will grow up with no conception of privacy at all. They’ll never know what it means to " @"have a private moment to themselves an unrecorded, unanalyzed thought. And that’s a problem because " @"privacy matters; privacy is what allows us to determine who we are and who we want to be."; [self writeWithBlock:^(SDSAnyWriteTransaction *transaction) { TSGroupThread *thread = [GroupManager createGroupForTestsObjcWithMembers:@[ self.localAddress, self.otherAddress, ] name:@"fdsfsd" avatarData:nil transaction:transaction]; NSMutableArray *messages = [NSMutableArray new]; for (uint64_t i = 0; i < 10; i++) { NSUInteger memberIdx = (i % thread.groupModel.groupMembers.count); SignalServiceAddress *authorAddress = thread.groupModel.groupMembers[memberIdx]; TSIncomingMessageBuilder *incomingMessageBuilder = [TSIncomingMessageBuilder incomingMessageBuilderWithThread:thread messageBody:body]; incomingMessageBuilder.timestamp = i + 1; incomingMessageBuilder.authorAddress = authorAddress; incomingMessageBuilder.sourceDeviceId = 1; TSIncomingMessage *newMessage = [incomingMessageBuilder build]; [newMessage anyInsertWithTransaction:transaction]; [messages addObject:newMessage]; } for (TSIncomingMessage *message in messages) { TSIncomingMessage *_Nullable fetchedMessage = [TSIncomingMessage anyFetchIncomingMessageWithUniqueId:message.uniqueId transaction:transaction]; XCTAssertNotNil(fetchedMessage); XCTAssertEqualObjects(fetchedMessage.body, body, @"Body of incoming message recovered"); XCTAssertEqual(0, fetchedMessage.attachmentIds.count, @"attachments are empty"); XCTAssertEqualObjects(fetchedMessage.uniqueId, message.uniqueId, @"Unique identifier is accurate"); XCTAssertFalse(fetchedMessage.wasRead, @"Message should originally be unread"); XCTAssertEqualObjects(fetchedMessage.uniqueThreadId, thread.uniqueId, @"Isn't stored in the right thread!"); } [thread anyRemoveWithTransaction:transaction]; for (TSIncomingMessage *message in messages) { TSIncomingMessage *_Nullable fetchedMessage = [TSIncomingMessage anyFetchIncomingMessageWithUniqueId:message.uniqueId transaction:transaction]; XCTAssertNil(fetchedMessage, @"Message should be deleted!"); } }]; } @end