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

515 lines
20 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 <OCMock/OCMock.h>
#import <XCTest/XCTest.h>
#import "OCTManagerImpl.h"
#import "OCTManagerFactory.h"
#import "OCTManagerConstants.h"
#import "OCTTox.h"
#import "OCTToxAV.h"
#import "OCTToxEncryptSave.h"
#import "OCTSubmanagerDataSource.h"
#import "OCTManagerConfiguration.h"
#import "OCTSubmanagerBootstrapImpl.h"
#import "OCTSubmanagerChatsImpl.h"
#import "OCTSubmanagerFriendsImpl.h"
#import "OCTSubmanagerFilesImpl.h"
#import "OCTSubmanagerUserImpl.h"
#import "OCTSubmanagerObjectsImpl.h"
#import "OCTSubmanagerCallsImpl.h"
#import "OCTRealmManager.h"
#import "OCTDefaultFileStorage.h"
#import "OCTMessageAbstract.h"
#import "OCTMessageText.h"
#import "OCTMessageFile.h"
static NSString *const kTestDirectory = @"me.dvor.objcToxTests";
@interface OCTManagerImpl (Tests) <OCTSubmanagerDataSource>
@property (strong, nonatomic, readonly) OCTTox *tox;
@property (strong, nonatomic, readonly) OCTToxAV *toxAV;
@property (copy, nonatomic, readwrite) OCTManagerConfiguration *configuration;
@property (strong, nonatomic, readwrite) OCTSubmanagerBootstrapImpl *bootstrap;
@property (strong, nonatomic, readwrite) OCTSubmanagerChatsImpl *chats;
@property (strong, nonatomic, readwrite) OCTSubmanagerFilesImpl *files;
@property (strong, nonatomic, readwrite) OCTSubmanagerFriendsImpl *friends;
@property (strong, nonatomic, readwrite) OCTSubmanagerObjectsImpl *objects;
@property (strong, nonatomic, readwrite) OCTSubmanagerUserImpl *user;
@property (strong, nonatomic) OCTRealmManager *realmManager;
@property (strong, nonatomic) NSNotificationCenter *notificationCenter;
- (id)forwardingTargetForSelector:(SEL)aSelector;
@end
@interface FakeSubmanager : NSObject <OCTToxDelegate>
@property (weak, nonatomic) id dataSource;
@end
@implementation FakeSubmanager
- (void)tox:(OCTTox *)tox connectionStatus:(OCTToxConnectionStatus)status
{}
@end
@interface OCTManagerImplTests : XCTestCase
@property (strong, nonatomic) OCTManagerImpl *manager;
@property (nonatomic, assign) id mockedCallManager;
@property (strong, nonatomic) id tox;
@property (strong, nonatomic) id toxAV;
@property (strong, nonatomic) NSString *tempDirectoryPath;
@end
@implementation OCTManagerImplTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
self.tempDirectoryPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:kTestDirectory] stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
[[NSFileManager defaultManager] createDirectoryAtPath:self.tempDirectoryPath
withIntermediateDirectories:YES
attributes:nil
error:nil];
self.mockedCallManager = OCMClassMock([OCTSubmanagerCallsImpl class]);
self.tox = OCMClassMock([OCTTox class]);
OCMStub([self.tox alloc]).andReturn(self.tox);
OCMStub([self.tox initWithOptions:[OCMArg any] savedData:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn(self.tox);
OCMStub([self.tox initWithOptions:[OCMArg any] savedData:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn(self.tox);
OCMStub([self.tox save]).andReturn([@"save file" dataUsingEncoding:NSUTF8StringEncoding]);
self.toxAV = OCMClassMock([OCTToxAV class]);
OCMStub([self.toxAV alloc]).andReturn(self.toxAV);
OCMStub([self.toxAV initWithTox:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn(self.toxAV);
id data = OCMClassMock([NSData class]);
OCMStub([data writeToFile:[OCMArg any] options:NSDataWritingAtomic error:[OCMArg anyObjectRef]]).andReturn(YES);
OCMStub([self.tox save]).andReturn(data);
}
- (void)tearDown
{
[self.tox stopMocking];
self.tox = nil;
[self.toxAV stopMocking];
self.toxAV = nil;
self.manager = nil;
[self.mockedCallManager stopMocking];
self.mockedCallManager = nil;
[[NSFileManager defaultManager] removeItemAtPath:self.tempDirectoryPath error:nil];
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testInit
{
[self createManager];
XCTAssertNotNil(self.manager);
XCTAssertNotNil(self.manager.bootstrap);
XCTAssertEqual(self.manager.bootstrap.dataSource, self.manager);
XCTAssertNotNil(self.manager.chats);
XCTAssertEqual(self.manager.chats.dataSource, self.manager);
XCTAssertNotNil(self.manager.files);
XCTAssertEqual(self.manager.files.dataSource, self.manager);
XCTAssertNotNil(self.manager.friends);
XCTAssertEqual(self.manager.friends.dataSource, self.manager);
XCTAssertNotNil(self.manager.objects);
XCTAssertEqual(self.manager.objects.dataSource, self.manager);
XCTAssertNotNil(self.manager.user);
XCTAssertEqual(self.manager.user.dataSource, self.manager);
XCTAssertNotNil(self.manager.tox);
XCTAssertNotNil(self.manager.configuration);
XCTAssertNotNil(self.manager.realmManager);
XCTAssertEqualObjects(self.manager.realmManager.realmFileURL.path, self.manager.configuration.fileStorage.pathForDatabase);
XCTAssertNotNil(self.manager.notificationCenter);
}
- (void)testToxEncryption
{
// We want use real data to make sure that encryption/decryption actually works. This is really crucial test.
[self.tox stopMocking];
self.tox = nil;
OCTManagerConfiguration *configuration = [OCTManagerConfiguration defaultConfiguration];
configuration.fileStorage = [self temporaryFileStorage];
__block NSString *userAddress;
{
// Create non-encrypted Tox to test manager encryption of first start.
OCTTox *tox = [[OCTTox alloc] initWithOptions:configuration.options savedData:nil error:nil];
XCTAssertNotNil(tox);
userAddress = tox.userAddress;
[tox setNickname:@"nonEncrypted" error:nil];
NSData *data = [tox save];
BOOL result = [data writeToFile:configuration.fileStorage.pathForToxSaveFile
options:NSDataWritingAtomic
error:nil];
XCTAssertTrue(result);
}
XCTestExpectation *encryptOnFirstRunExpectation = [self expectationWithDescription:@"encryptOnFirstRunExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"password123" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertEqualObjects(userAddress, manager.user.userAddress);
XCTAssertEqualObjects(@"nonEncrypted", manager.user.userName);
[encryptOnFirstRunExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
XCTestExpectation *encryptedExpectation = [self expectationWithDescription:@"encryptedExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"password123" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertEqualObjects(userAddress, manager.user.userAddress);
XCTAssertEqualObjects(@"nonEncrypted", manager.user.userName);
// Change passphrase
[manager.user setUserName:@"renamed" error:nil];
[manager changeEncryptPassword:@"new password" oldPassword:@"password123"];
[encryptedExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
XCTestExpectation *renamedEncryptedExpectation = [self expectationWithDescription:@"renamedEncryptedExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"new password" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertEqualObjects(userAddress, manager.user.userAddress);
XCTAssertEqualObjects(@"renamed", manager.user.userName);
[renamedEncryptedExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
XCTestExpectation *wrongPasswordExpectation = [self expectationWithDescription:@"wrongPasswordExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"new password" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertFalse([manager changeEncryptPassword:@"the password" oldPassword:@"wrong password"]);
[wrongPasswordExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
XCTestExpectation *newPasswordExpectation = [self expectationWithDescription:@"newPasswordExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"new password" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertTrue([manager changeEncryptPassword:@"another" oldPassword:@"new password"]);
[newPasswordExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
XCTestExpectation *anotherPasswordExpectation = [self expectationWithDescription:@"anotherPasswordExpectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"another" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
[anotherPasswordExpectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
}
- (void)testIsManagerEncryptedWithPassword
{
// We want use real data to make sure that encryption/decryption actually works. This is really crucial test.
[self.tox stopMocking];
self.tox = nil;
OCTManagerConfiguration *configuration = [OCTManagerConfiguration defaultConfiguration];
configuration.fileStorage = [self temporaryFileStorage];
XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"password123" successBlock:^(id < OCTManager > manager) {
XCTAssertNotNil(manager);
XCTAssertTrue([manager isManagerEncryptedWithPassword:@"password123"]);
XCTAssertFalse([manager isManagerEncryptedWithPassword:@"wrong password"]);
[expectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
}
- (void)testDatabaseMigration
{
NSMutableArray *friendsArray = [NSMutableArray new];
for (int i = 0; i < 100; i++) {
[friendsArray addObject:@(i)];
NSString *publicKey = [NSString stringWithFormat:@"publicKey-%d", i];
OCMStub([self.tox publicKeyFromFriendNumber:i error:[OCMArg anyObjectRef]]).andReturn(publicKey);
}
OCMStub([self.tox friendsArray]).andReturn(friendsArray);
OCTManagerConfiguration *configuration = [OCTManagerConfiguration defaultConfiguration];
configuration.fileStorage = [self temporaryFileStorage];
NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
NSString *bundlePath = [testBundle pathForResource:@"unencrypted-database" ofType:@"realm"];
[[NSFileManager defaultManager] copyItemAtPath:bundlePath toPath:configuration.fileStorage.pathForDatabase
error:nil];
XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
__block id<OCTManager> manager;
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"the password" successBlock:^(id < OCTManager > m) {
manager = m;
[expectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:20.0 handler:nil];
XCTAssertNotNil(manager);
RLMResults *friends = [manager.objects objectsForType:OCTFetchRequestTypeFriend predicate:nil];
XCTAssertEqual(friends.count, 100);
for (OCTToxFriendNumber friendNumber = 0; friendNumber < 100; friendNumber++) {
OCTFriend *friend = friends[friendNumber];
XCTAssertEqual(friend.friendNumber, friendNumber);
NSString *nickname = [NSString stringWithFormat:@"friend-%d", friendNumber];
XCTAssertEqualObjects(friend.nickname, nickname);
}
RLMResults *messages = [manager.objects objectsForType:OCTFetchRequestTypeMessageAbstract predicate:nil];
XCTAssertEqual(messages.count, 50000);
OCTMessageAbstract *message0 = messages[0];
XCTAssertNotNil(message0.messageText);
XCTAssertNil(message0.messageFile);
XCTAssertNil(message0.messageCall);
XCTAssertEqualObjects(message0.messageText.text, @"message-0");
OCTMessageAbstract *message1 = messages[1];
XCTAssertNil(message1.messageText);
XCTAssertNotNil(message1.messageFile);
XCTAssertNil(message1.messageCall);
XCTAssertEqualObjects(message1.messageFile.fileName, @"file-1");
XCTAssertEqualObjects(message0.chatUniqueIdentifier, message1.chatUniqueIdentifier);
}
- (void)testConfiguration
{
OCTToxEncryptSave *encryptSave = OCMClassMock([OCTToxEncryptSave class]);
OCMStub([(id)encryptSave alloc]).andReturn(encryptSave);
OCMStub([encryptSave initWithPassphrase:[OCMArg any]
toxData:[OCMArg any]
error:[OCMArg anyObjectRef]]).andReturn(encryptSave);
OCMStub([encryptSave encryptData:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn([NSData new]);
OCMStub([encryptSave decryptData:[OCMArg any] error:[OCMArg anyObjectRef]]).andReturn([NSData new]);
OCTManagerConfiguration *configuration = [OCTManagerConfiguration defaultConfiguration];
configuration.options.ipv6Enabled = YES;
configuration.options.udpEnabled = YES;
configuration.options.localDiscoveryEnabled = YES;
configuration.options.proxyType = OCTToxProxyTypeHTTP;
configuration.options.proxyHost = @"proxy.address";
configuration.options.proxyPort = 999;
configuration.options.startPort = 123;
configuration.options.endPort = 321;
configuration.options.tcpPort = 777;
configuration.options.holePunchingEnabled = YES;
configuration.importToxSaveFromPath = @"save.tox";
configuration.fileStorage = [self temporaryFileStorage];
XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
__block id<OCTManager> manager;
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"p@s$" successBlock:^(id < OCTManager > m) {
manager = m;
[expectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:200.0 handler:nil];
OCTManagerConfiguration *c2 = [manager configuration];
XCTAssertTrue(c2.options.ipv6Enabled);
XCTAssertTrue(c2.options.udpEnabled);
XCTAssertTrue(c2.options.localDiscoveryEnabled);
XCTAssertEqual(c2.options.proxyType, OCTToxProxyTypeHTTP);
XCTAssertEqualObjects(c2.options.proxyHost, @"proxy.address");
XCTAssertEqual(c2.options.proxyPort, 999);
XCTAssertEqual(c2.options.startPort, 123);
XCTAssertEqual(c2.options.endPort, 321);
XCTAssertEqual(c2.options.tcpPort, 777);
XCTAssertTrue(c2.options.holePunchingEnabled);
XCTAssertEqualObjects(c2.importToxSaveFromPath, @"save.tox");
[(id)encryptSave stopMocking];
}
- (void)testSubmanagerDataSource
{
[self createManager];
XCTAssertEqual([self.manager managerGetTox], self.manager.tox);
XCTAssertEqual([self.manager managerGetRealmManager], self.manager.realmManager);
XCTAssertEqual([self.manager managerGetFileStorage], self.manager.configuration.fileStorage);
XCTAssertEqual([self.manager managerGetNotificationCenter], self.manager.notificationCenter);
}
- (void)testForwardTargetForSelector
{
[self createManager];
id submanager = [FakeSubmanager new];
self.manager.bootstrap = submanager;
self.manager.chats = submanager;
self.manager.files = submanager;
self.manager.friends = submanager;
self.manager.objects = submanager;
self.manager.user = submanager;
// test non protocol selector
XCTAssertNil([self.manager forwardingTargetForSelector:@selector(dataSource)]);
// test for protocol non-implemented selector
XCTAssertNil([self.manager forwardingTargetForSelector:@selector(tox:friendRequestWithMessage:publicKey:)]);
// test for protocol implemented selector
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
}
- (void)testForwardTargetForSelector2
{
[self createManager];
id submanager = [FakeSubmanager new];
id dummy = [NSObject new];
self.manager.bootstrap = submanager;
self.manager.chats = dummy;
self.manager.files = dummy;
self.manager.friends = dummy;
self.manager.objects = dummy;
self.manager.user = dummy;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
self.manager.bootstrap = dummy;
self.manager.chats = submanager;
self.manager.files = dummy;
self.manager.friends = dummy;
self.manager.objects = dummy;
self.manager.user = dummy;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
self.manager.bootstrap = dummy;
self.manager.chats = dummy;
self.manager.files = submanager;
self.manager.friends = dummy;
self.manager.objects = dummy;
self.manager.user = dummy;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
self.manager.bootstrap = dummy;
self.manager.chats = dummy;
self.manager.files = dummy;
self.manager.friends = submanager;
self.manager.objects = dummy;
self.manager.user = dummy;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
self.manager.bootstrap = dummy;
self.manager.chats = dummy;
self.manager.files = dummy;
self.manager.friends = dummy;
self.manager.objects = submanager;
self.manager.user = dummy;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
self.manager.bootstrap = dummy;
self.manager.chats = dummy;
self.manager.files = dummy;
self.manager.friends = dummy;
self.manager.objects = dummy;
self.manager.user = submanager;
XCTAssertEqual([self.manager forwardingTargetForSelector:@selector(tox:connectionStatus:)], submanager);
}
- (void)testExportToxSaveFile
{
[self createManager];
NSString *path = [self.manager exportToxSaveFileAndReturnError:nil];
NSString *result = [[self.manager configuration].fileStorage.pathForTemporaryFilesDirectory stringByAppendingPathComponent:@"save.tox"];
XCTAssertEqualObjects(path, result);
}
#pragma mark - Helper methods
- (void)createManager
{
OCMStub([[self.mockedCallManager alloc] initWithTox:[OCMArg anyPointer]]).andReturn(nil);
OCTManagerConfiguration *configuration = [OCTManagerConfiguration defaultConfiguration];
configuration.fileStorage = [self temporaryFileStorage];
XCTestExpectation *expectation = [self expectationWithDescription:@"expectation"];
__weak OCTManagerImplTests *weakSelf = self;
[OCTManagerFactory managerWithConfiguration:configuration encryptPassword:@"123" successBlock:^(id < OCTManager > manager) {
weakSelf.manager = (OCTManagerImpl *)manager;
[expectation fulfill];
} failureBlock:nil];
[self waitForExpectationsWithTimeout:2.0 handler:nil];
}
- (OCTDefaultFileStorage *)temporaryFileStorage
{
return [[OCTDefaultFileStorage alloc] initWithBaseDirectory:self.tempDirectoryPath
temporaryDirectory:[self.tempDirectoryPath stringByAppendingPathComponent:@"tmp"]];
}
@end