Antidote/local_pod_repo/objcTox/Tests/OCTSubmanagerChatsImplTests.m
2024-02-22 21:43:11 +02:00

487 lines
18 KiB
Objective-C

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
#import "OCTRealmTests.h"
#import "OCTSubmanagerChatsImpl.h"
#import "OCTRealmManager.h"
#import "OCTTox.h"
#import "OCTMessageAbstract.h"
#import "OCTMessageText.h"
@interface OCTSubmanagerChatsImplTests : OCTRealmTests
@property (strong, nonatomic) OCTSubmanagerChatsImpl *submanager;
@property (strong, nonatomic) NSNotificationCenter *notificationCenter;
@property (strong, nonatomic) id dataSource;
@property (strong, nonatomic) id tox;
@end
@implementation OCTSubmanagerChatsImplTests
- (void)setUp
{
[super setUp];
self.notificationCenter = [[NSNotificationCenter alloc] init];
self.dataSource = OCMProtocolMock(@protocol(OCTSubmanagerDataSource));
OCMStub([self.dataSource managerGetNotificationCenter]).andReturn(self.notificationCenter);
OCMStub([self.dataSource managerGetRealmManager]).andReturn(self.realmManager);
self.tox = OCMClassMock([OCTTox class]);
OCMStub([self.dataSource managerGetTox]).andReturn(self.tox);
self.submanager = [OCTSubmanagerChatsImpl new];
self.submanager.dataSource = self.dataSource;
[self.submanager configure];
}
- (void)tearDown
{
self.dataSource = nil;
self.tox = nil;
self.submanager = nil;
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testGetOrCreateChatWithFriend
{
OCTFriend *friend = [self createFriendWithFriendNumber:5];
[self.realmManager.realm beginWriteTransaction];
[self.realmManager.realm addObject:friend];
[self.realmManager.realm commitWriteTransaction];
OCTChat *first = [self.realmManager getOrCreateChatWithFriend:friend];
OCTChat *second = [self.realmManager getOrCreateChatWithFriend:friend];
XCTAssertEqualObjects(first, second);
XCTAssertEqualObjects([first.friends firstObject], friend);
}
- (void)testRemoveMessages
{
XCTestExpectation *expect = [self expectationWithDescription:@""];
[self.notificationCenter addObserverForName:kOCTScheduleFileTransferCleanupNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[expect fulfill];
}];
NSArray *messages = [NSArray new];
OCMExpect([self.realmManager removeMessages:messages]);
[self.submanager removeMessages:messages];
[self waitForExpectationsWithTimeout:0.0 handler:nil];
OCMVerifyAll((id)self.realmManager);
}
- (void)testRemoveMessagesWithChat
{
XCTestExpectation *expect = [self expectationWithDescription:@""];
[self.notificationCenter addObserverForName:kOCTScheduleFileTransferCleanupNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[expect fulfill];
}];
OCTChat *chat = [OCTChat new];
OCMExpect([self.realmManager removeAllMessagesInChat:chat removeChat:YES]);
[self.submanager removeAllMessagesInChat:chat removeChat:YES];
[self waitForExpectationsWithTimeout:0.0 handler:nil];
OCMVerifyAll((id)self.realmManager);
}
- (void)testSendMessageToChatSuccess
{
id message = OCMClassMock([OCTMessageAbstract class]);
id friend = OCMClassMock([OCTFriend class]);
OCMStub([friend friendNumber]).andReturn(5);
NSArray *friends = @[friend];
id chat = OCMClassMock([OCTChat class]);
OCMStub([chat friends]).andReturn(friends);
OCMStub([self.tox sendMessageWithFriendNumber:5
type:OCTToxMessageTypeAction
message:@"text"
error:[OCMArg anyObjectRef]]).andReturn(7);
OCMExpect([self.realmManager addMessageWithText:@"text"
type:OCTToxMessageTypeAction
chat:chat
sender:nil
messageId:7]).andReturn(message);
XCTestExpectation *expectation = [self expectationWithDescription:@""];
[self.submanager sendMessageToChat:chat text:@"text" type:OCTToxMessageTypeAction successBlock:^(OCTMessageAbstract *theMessage) {
OCMVerifyAll((id)self.realmManager);
XCTAssertEqualObjects(message, theMessage);
[expectation fulfill];
} failureBlock:^(NSError *error) {
XCTAssertTrue(false, @"This block shouldn't be called");
}];
[self waitForExpectationsWithTimeout:0.2 handler:nil];
}
- (void)testSendMessageToChatFailure
{
id friend = OCMClassMock([OCTFriend class]);
OCMStub([friend friendNumber]).andReturn(5);
NSArray *friends = @[friend];
id chat = OCMClassMock([OCTChat class]);
OCMStub([chat friends]).andReturn(friends);
NSError *error2 = OCMClassMock([NSError class]);
OCMStub([self.tox sendMessageWithFriendNumber:5
type:OCTToxMessageTypeAction
message:@"text"
error:[OCMArg setTo:error2]]).andReturn(0);
XCTestExpectation *expectation = [self expectationWithDescription:@""];
[self.submanager sendMessageToChat:chat text:@"text" type:OCTToxMessageTypeAction successBlock:^(OCTMessageAbstract *theMessage) {
XCTAssertTrue(false, @"This block shouldn't be called");
} failureBlock:^(NSError *error) {
OCMVerifyAll((id)self.realmManager);
XCTAssertEqualObjects(error, error2);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:0.2 handler:nil];
}
- (void)testSendMessageToChatFauxEnabled
{
OCMStub([self.dataSource managerUseFauxOfflineMessaging]).andReturn(YES);
id message = OCMClassMock([OCTMessageAbstract class]);
id friend = OCMClassMock([OCTFriend class]);
OCMStub([friend friendNumber]).andReturn(5);
NSArray *friends = @[friend];
id chat = OCMClassMock([OCTChat class]);
OCMStub([chat friends]).andReturn(friends);
NSError *error2 = OCMClassMock([NSError class]);
OCMStub(error2.code).andReturn(OCTToxErrorFriendSendMessageFriendNotConnected);
OCMStub([self.tox sendMessageWithFriendNumber:5
type:OCTToxMessageTypeAction
message:@"text"
error:[OCMArg setTo:error2]]).andReturn(0);
OCMExpect([self.realmManager addMessageWithText:@"text"
type:OCTToxMessageTypeAction
chat:chat
sender:nil
messageId:-1]).andReturn(message);
XCTestExpectation *expectation = [self expectationWithDescription:@""];
[self.submanager sendMessageToChat:chat text:@"text" type:OCTToxMessageTypeAction successBlock:^(OCTMessageAbstract *theMessage) {
OCMVerifyAll((id)self.realmManager);
XCTAssertEqualObjects(message, theMessage);
[expectation fulfill];
} failureBlock:^(NSError *error) {
XCTAssertTrue(false, @"This block shouldn't be called");
}];
[self waitForExpectationsWithTimeout:0.2 handler:nil];
}
- (void)testSendMessageToChatFauxDisabled
{
OCMStub([self.dataSource managerUseFauxOfflineMessaging]).andReturn(NO);
id friend = OCMClassMock([OCTFriend class]);
OCMStub([friend friendNumber]).andReturn(5);
NSArray *friends = @[friend];
id chat = OCMClassMock([OCTChat class]);
OCMStub([chat friends]).andReturn(friends);
NSError *error2 = OCMClassMock([NSError class]);
OCMStub(error2.code).andReturn(OCTToxErrorFriendSendMessageFriendNotConnected);
OCMStub([self.tox sendMessageWithFriendNumber:5
type:OCTToxMessageTypeAction
message:@"text"
error:[OCMArg setTo:error2]]).andReturn(0);
XCTestExpectation *expectation = [self expectationWithDescription:@""];
[self.submanager sendMessageToChat:chat text:@"text" type:OCTToxMessageTypeAction successBlock:^(OCTMessageAbstract *theMessage) {
XCTAssertTrue(false, @"This block shouldn't be called");
} failureBlock:^(NSError *error) {
OCMVerifyAll((id)self.realmManager);
XCTAssertEqualObjects(error, error2);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:0.2 handler:nil];
}
- (void)testSetIsTyping
{
id friend = OCMClassMock([OCTFriend class]);
OCMStub([friend friendNumber]).andReturn(5);
NSArray *friends = @[friend];
id chat = OCMClassMock([OCTChat class]);
OCMStub([chat friends]).andReturn(friends);
NSError *error;
NSError *error2 = OCMClassMock([NSError class]);
OCMExpect([self.tox setUserIsTyping:YES forFriendNumber:5 error:[OCMArg setTo:error2]]).andReturn(NO);
XCTAssertFalse([self.submanager setIsTyping:YES inChat:chat error:&error]);
XCTAssertEqual(error, error2);
OCMVerifyAll(self.tox);
}
- (void)testResendUndeliveredMessages
{
NSArray * (^createMessages)(OCTChat *, OCTToxMessageId) = ^(OCTChat *chat, OCTToxMessageId number) {
NSMutableArray *array = [NSMutableArray new];
for (OCTToxMessageId index = 0; index < number; index++) {
BOOL outgoing = index % 2;
OCTMessageAbstract *message = [self createTextMessageInChat:chat outgoing:outgoing messageId:index];
[array addObject:message];
}
return [array copy];
};
OCTToxFriendNumber friendNumber = 1;
OCTFriend *friend1 = [self createFriendWithFriendNumber:friendNumber++];
OCTFriend *friend2 = [self createFriendWithFriendNumber:friendNumber++];
NSString *publicKey1 = friend1.publicKey;
NSString *publicKey2 = friend2.publicKey;
OCMStub([self.tox publicKeyFromFriendNumber:friend1.friendNumber error:nil]).andReturn(publicKey1);
OCMStub([self.tox publicKeyFromFriendNumber:friend2.friendNumber error:nil]).andReturn(publicKey2);
OCTChat *chat1 = [self createChatWithFriend:friend1];
OCTChat *chat2 = [self createChatWithFriend:friend2];
NSArray *messages1 = createMessages(chat1, 10);
NSArray *messages2 = createMessages(chat2, 2);
[self.realmManager.realm beginWriteTransaction];
[self.realmManager.realm addObject:chat1];
[self.realmManager.realm addObject:chat2];
[self.realmManager.realm addObjects:messages1];
[self.realmManager.realm addObjects:messages2];
[self.realmManager.realm commitWriteTransaction];
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"1" error:[OCMArg anyObjectRef]]).andReturn(101);
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"3" error:[OCMArg anyObjectRef]]).andReturn(103);
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"5" error:[OCMArg anyObjectRef]]).andReturn(105);
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"7" error:[OCMArg anyObjectRef]]).andReturn(107);
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"9" error:[OCMArg anyObjectRef]]).andReturn(109);
[self.realmManager.realm beginWriteTransaction];
friend1.connectionStatus = OCTToxConnectionStatusUDP;
friend1.isConnected = YES;
[self.realmManager.realm commitWriteTransaction];
[self.notificationCenter postNotificationName:kOCTFriendConnectionStatusChangeNotification object:friend1];
#define VERIFY_MESSAGE(__array, __index, __messageId, __delivered) \
{ \
NSString *identifier = [__array[__index] uniqueIdentifier]; \
OCTMessageAbstract *message = [self.realmManager objectWithUniqueIdentifier:identifier class:[OCTMessageAbstract class]]; \
XCTAssertEqual(message.messageText.messageId, __messageId); \
XCTAssertEqual(message.messageText.isDelivered, __delivered); \
}
XCTestExpectation *expectation = [self expectationWithDescription:@""];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
VERIFY_MESSAGE(messages1, 0, 0, NO);
VERIFY_MESSAGE(messages1, 1, 101, NO);
VERIFY_MESSAGE(messages1, 2, 2, NO);
VERIFY_MESSAGE(messages1, 3, 103, NO);
VERIFY_MESSAGE(messages1, 4, 4, NO);
VERIFY_MESSAGE(messages1, 5, 105, NO);
VERIFY_MESSAGE(messages1, 6, 6, NO);
VERIFY_MESSAGE(messages1, 7, 107, NO);
VERIFY_MESSAGE(messages1, 8, 8, NO);
VERIFY_MESSAGE(messages1, 9, 109, NO);
VERIFY_MESSAGE(messages2, 0, 0, NO);
VERIFY_MESSAGE(messages2, 1, 1, NO);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:0.3 handler:nil];
// Deliver some messages, then resend all left again.
[self.submanager tox:self.tox messageDelivered:101 friendNumber:1];
[self.submanager tox:self.tox messageDelivered:103 friendNumber:1];
[self.submanager tox:self.tox messageDelivered:105 friendNumber:1];
{
OCTMessageAbstract *message;
[self.realmManager.realm beginWriteTransaction];
message = messages1[7];
message.messageText.text = @"107";
message = messages1[9];
message.messageText.text = @"109";
[self.realmManager.realm commitWriteTransaction];
}
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"107" error:[OCMArg anyObjectRef]]).andReturn(207);
OCMStub([self.tox sendMessageWithFriendNumber:1 type:OCTToxMessageTypeNormal message:@"109" error:[OCMArg anyObjectRef]]).andReturn(209);
[self.notificationCenter postNotificationName:kOCTFriendConnectionStatusChangeNotification object:friend1];
XCTestExpectation *expectation2 = [self expectationWithDescription:@""];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
VERIFY_MESSAGE(messages1, 0, 0, NO);
VERIFY_MESSAGE(messages1, 1, 101, YES);
VERIFY_MESSAGE(messages1, 2, 2, NO);
VERIFY_MESSAGE(messages1, 3, 103, YES);
VERIFY_MESSAGE(messages1, 4, 4, NO);
VERIFY_MESSAGE(messages1, 5, 105, YES);
VERIFY_MESSAGE(messages1, 6, 6, NO);
VERIFY_MESSAGE(messages1, 7, 207, NO);
VERIFY_MESSAGE(messages1, 8, 8, NO);
VERIFY_MESSAGE(messages1, 9, 209, NO);
VERIFY_MESSAGE(messages2, 0, 0, NO);
VERIFY_MESSAGE(messages2, 1, 1, NO);
[expectation2 fulfill];
});
[self waitForExpectationsWithTimeout:0.3 handler:nil];
}
#pragma mark - OCTToxDelegate
- (void)testFriendMessage
{
OCTFriend *friend = [self createFriendWithFriendNumber:5];
NSString *publicKey = friend.publicKey;
OCMStub([self.tox publicKeyFromFriendNumber:friend.friendNumber error:nil]).andReturn(publicKey);
OCTChat *chat = [OCTChat new];
[chat.friends addObject:friend];
[self.realmManager.realm beginWriteTransaction];
[self.realmManager.realm addObject:chat];
[self.realmManager.realm commitWriteTransaction];
[self.submanager tox:nil friendMessage:@"message" type:OCTToxMessageTypeAction friendNumber:5];
RLMResults *results = [OCTMessageAbstract allObjectsInRealm:self.realmManager.realm];
XCTAssertEqual(results.count, 1);
OCTMessageAbstract *message = [results firstObject];
XCTAssertEqualObjects(message.senderUniqueIdentifier, friend.uniqueIdentifier);
XCTAssertEqualObjects(message.chatUniqueIdentifier, chat.uniqueIdentifier);
XCTAssertNotNil(message.messageText);
XCTAssertEqualObjects(message.messageText.text, @"message");
XCTAssertEqual(message.messageText.type, OCTToxMessageTypeAction);
}
- (void)testMessageDelivered
{
OCTFriend *friend = [self createFriendWithFriendNumber:5];
NSString *publicKey = friend.publicKey;
OCMStub([self.tox publicKeyFromFriendNumber:friend.friendNumber error:nil]).andReturn(publicKey);
OCTChat *chat = [OCTChat new];
[chat.friends addObject:friend];
OCTMessageAbstract *message = [OCTMessageAbstract new];
message.chatUniqueIdentifier = chat.uniqueIdentifier;
message.dateInterval = [[NSDate date] timeIntervalSince1970];
message.messageText = [OCTMessageText new];
message.messageText.text = @"";
message.messageText.messageId = 10;
message.messageText.isDelivered = NO;
[self.realmManager.realm beginWriteTransaction];
[self.realmManager.realm addObject:friend];
[self.realmManager.realm addObject:chat];
[self.realmManager.realm addObject:message];
[self.realmManager.realm commitWriteTransaction];
[self.submanager tox:self.tox messageDelivered:10 friendNumber:5];
XCTAssertTrue(message.messageText.isDelivered);
OCTMessageAbstract *anotherMessageSameId = [OCTMessageAbstract new];
anotherMessageSameId.chatUniqueIdentifier = chat.uniqueIdentifier;
anotherMessageSameId.dateInterval = [[NSDate date] timeIntervalSince1970];
anotherMessageSameId.messageText = [OCTMessageText new];
anotherMessageSameId.messageText.text = @"";
anotherMessageSameId.messageText.messageId = 10;
anotherMessageSameId.messageText.isDelivered = NO;
[self.realmManager.realm beginWriteTransaction];
[self.realmManager.realm addObject:anotherMessageSameId];
[self.realmManager.realm commitWriteTransaction];
[self.submanager tox:self.tox messageDelivered:10 friendNumber:5];
XCTAssertTrue(anotherMessageSameId.messageText.isDelivered);
}
- (OCTChat *)createChatWithFriend:(OCTFriend *)friend
{
OCTChat *chat = [OCTChat new];
[chat.friends addObject:friend];
return chat;
}
- (OCTMessageAbstract *)createTextMessageInChat:(OCTChat *)chat outgoing:(BOOL)outgoing messageId:(OCTToxMessageId)messageId
{
OCTMessageAbstract *message = [OCTMessageAbstract new];
message.chatUniqueIdentifier = chat.uniqueIdentifier;
message.messageText = [OCTMessageText new];
message.messageText.text = [NSString stringWithFormat:@"%d", messageId];
message.messageText.messageId = messageId;
if (! outgoing) {
OCTFriend *friend = chat.friends.lastObject;
message.senderUniqueIdentifier = friend.uniqueIdentifier;
}
return message;
}
@end