// // Copyright (c) 2019 Open Whisper Systems. All rights reserved. // #import "MockSSKEnvironment.h" #import "OWSDisappearingMessagesFinder.h" #import "OWSPrimaryStorage.h" #import "SSKBaseTestObjC.h" #import "TSContactThread.h" #import "TSMessage.h" #import "TestAppContext.h" #import #import NS_ASSUME_NONNULL_BEGIN @interface OWSDisappearingMessagesFinder (Testing) - (NSArray *)fetchExpiredMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction; - (NSArray *)fetchUnstartedExpiringMessagesInThread:(TSThread *)thread transaction:(YapDatabaseReadTransaction *)transaction; @end #pragma mark - @interface OWSDisappearingMessageFinderTest : SSKBaseTestObjC @property (nonatomic, nullable) OWSDisappearingMessagesFinder *finder; @property (nonatomic, nullable) TSThread *thread; @property (nonatomic) uint64_t now; @end #pragma mark - @implementation OWSDisappearingMessageFinderTest #ifdef BROKEN_TESTS - (void)setUp { [super setUp]; // TODO: This shouldn't be necessary. // [OWSDisappearingMessagesFinder blockingRegisterDatabaseExtensions:self.primaryStorage]; self.thread = [TSContactThread getOrCreateThreadWithContactId:@"fake-thread-id"]; self.now = [NSDate ows_millisecondTimeStamp]; // Test subject self.finder = [OWSDisappearingMessagesFinder new]; } - (void)tearDown { self.dbConnection = nil; [super tearDown]; } - (TSMessage *)messageWithBody:(NSString *)body expiresInSeconds:(uint32_t)expiresInSeconds expireStartedAt:(uint64_t)expireStartedAt { return [[TSMessage alloc] initMessageWithTimestamp:1 inThread:self.thread messageBody:body attachmentIds:@[] expiresInSeconds:expiresInSeconds expireStartedAt:expireStartedAt quotedMessage:nil contactShare:nil linkPreview:nil]; } - (void)testExpiredMessages { TSMessage *expiredMessage1 = [[TSMessage alloc] initMessageWithTimestamp:1 inThread:self.thread messageBody:@"expiredMessage1" attachmentIds:@[] expiresInSeconds:1 expireStartedAt:self.now - 20000 quotedMessage:nil contactShare:nil linkPreview:nil]; [expiredMessage1 save]; TSMessage *expiredMessage2 = [self messageWithBody:@"expiredMessage2" expiresInSeconds:2 expireStartedAt:self.now - 2001]; [expiredMessage2 save]; TSMessage *notYetExpiredMessage = [self messageWithBody:@"notYetExpiredMessage" expiresInSeconds:20 expireStartedAt:self.now - 10000]; [notYetExpiredMessage save]; TSMessage *unreadExpiringMessage = [self messageWithBody:@"unereadExpiringMessage" expiresInSeconds:10 expireStartedAt:0]; [unreadExpiringMessage save]; TSMessage *unExpiringMessage = [self messageWithBody:@"unexpiringMessage" expiresInSeconds:0 expireStartedAt:0]; [unExpiringMessage save]; TSMessage *unExpiringMessage2 = [self messageWithBody:@"unexpiringMessage2" expiresInSeconds:0 expireStartedAt:0]; [unExpiringMessage2 save]; __block NSArray *actualMessages; [self readWithBlock:^(YapDatabaseReadTransaction *transaction) { actualMessages = [self.finder fetchExpiredMessagesWithTransaction:transaction]; }]; NSArray *expectedMessages = @[ expiredMessage1, expiredMessage2 ]; XCTAssertEqualObjects(expectedMessages, actualMessages); } - (void)testUnstartedExpiredMessagesForThread { TSMessage *expiredMessage = [self messageWithBody:@"expiredMessage2" expiresInSeconds:2 expireStartedAt:self.now - 2001]; [expiredMessage save]; TSMessage *notYetExpiredMessage = [self messageWithBody:@"notYetExpiredMessage" expiresInSeconds:20 expireStartedAt:self.now - 10000]; [notYetExpiredMessage save]; TSMessage *unreadExpiringMessage = [self messageWithBody:@"unereadExpiringMessage" expiresInSeconds:10 expireStartedAt:0]; [unreadExpiringMessage save]; TSMessage *unExpiringMessage = [self messageWithBody:@"unexpiringMessage" expiresInSeconds:0 expireStartedAt:0]; [unExpiringMessage save]; TSMessage *unExpiringMessage2 = [self messageWithBody:@"unexpiringMessage2" expiresInSeconds:0 expireStartedAt:0]; [unExpiringMessage2 save]; __block NSArray *actualMessages; [self readWithBlock:^(YapDatabaseReadTransaction *transaction) { actualMessages = [self.finder fetchUnstartedExpiringMessagesInThread:self.thread transaction:transaction]; }]; NSArray *expectedMessages = @[ unreadExpiringMessage ]; XCTAssertEqualObjects(expectedMessages, actualMessages); } - (NSNumber *)nextExpirationTimestamp { __block NSNumber *nextExpirationTimestamp; [self readWithBlock:^(YapDatabaseReadTransaction *transaction) { XCTAssertNotNil(self.finder); nextExpirationTimestamp = [self.finder nextExpirationTimestampWithTransaction:transaction]; }]; return nextExpirationTimestamp; } - (void)testNextExpirationTimestampNilWhenNoExpiringMessages { // Sanity check. XCTAssertNil(self.nextExpirationTimestamp); TSMessage *unExpiringMessage = [self messageWithBody:@"unexpiringMessage" expiresInSeconds:0 expireStartedAt:0]; [unExpiringMessage save]; XCTAssertNil(self.nextExpirationTimestamp); } - (void)testNextExpirationTimestampNotNilWithUpcomingExpiringMessages { TSMessage *soonToExpireMessage = [self messageWithBody:@"soonToExpireMessage" expiresInSeconds:10 expireStartedAt:self.now - 9000]; [soonToExpireMessage save]; XCTAssertNotNil(self.nextExpirationTimestamp); XCTAssertEqual(self.now + 1000, [self.nextExpirationTimestamp unsignedLongLongValue]); // expired message should take precedence TSMessage *expiredMessage = [self messageWithBody:@"expiredMessage" expiresInSeconds:10 expireStartedAt:self.now - 11000]; [expiredMessage save]; XCTAssertNotNil(self.nextExpirationTimestamp); XCTAssertEqual(self.now - 1000, [self.nextExpirationTimestamp unsignedLongLongValue]); } #endif @end NS_ASSUME_NONNULL_END