diff --git a/Package.swift b/Package.swift index 4f06554efce0916bf663521502ed565b0a93c8e4..0024dab56e3d9aa08441134301edf535ef878da4 100644 --- a/Package.swift +++ b/Package.swift @@ -31,6 +31,10 @@ let package = Package( url: "https://github.com/pointfreeco/xctest-dynamic-overlay.git", .upToNextMajor(from: "0.4.0") ), + .package( + url: "https://github.com/kishikawakatsumi/KeychainAccess.git", + .upToNextMajor(from: "4.2.2") + ), ], targets: [ .target( @@ -53,6 +57,7 @@ let package = Package( name: "XXMessengerClient", dependencies: [ .target(name: "XXClient"), + .product(name: "KeychainAccess", package: "KeychainAccess"), .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"), ], swiftSettings: swiftSettings diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerConnect.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerConnect.swift new file mode 100644 index 0000000000000000000000000000000000000000..fa24b8ebf6ef0d813c6d72bad7566ae558251755 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerConnect.swift @@ -0,0 +1,35 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerConnect { + public enum Error: Swift.Error, Equatable { + case notLoaded + } + + public var run: () throws -> Void + + public func callAsFunction() throws { + try run() + } +} + +extension MessengerConnect { + public static func live(_ env: MessengerEnvironment) -> MessengerConnect { + MessengerConnect { + guard let cMix = env.ctx.cMix else { + throw Error.notLoaded + } + env.ctx.e2e = try env.login( + cMixId: cMix.getId(), + identity: try cMix.makeLegacyReceptionIdentity(), + e2eParamsJSON: env.getE2EParams() + ) + } + } +} + +extension MessengerConnect { + public static let unimplemented = MessengerConnect( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerCreate.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerCreate.swift new file mode 100644 index 0000000000000000000000000000000000000000..a3514141508e1fa6d5a47de09d75cc3aa9d87600 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerCreate.swift @@ -0,0 +1,35 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerCreate { + public var run: () throws -> Void + + public func callAsFunction() throws { + try run() + } +} + +extension MessengerCreate { + public static func live(_ env: MessengerEnvironment) -> MessengerCreate { + MessengerCreate { + let ndfData = try env.downloadNDF(env.ndfEnvironment) + let password = env.generateSecret() + try env.passwordStorage.save(password) + let storageDir = env.storageDir() + try env.fileManager.removeDirectory(storageDir) + try env.fileManager.createDirectory(storageDir) + try env.newCMix( + ndfJSON: String(data: ndfData, encoding: .utf8)!, + storageDir: storageDir, + password: password, + registrationCode: nil + ) + } + } +} + +extension MessengerCreate { + public static let unimplemented = MessengerCreate( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerIsConnected.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsConnected.swift new file mode 100644 index 0000000000000000000000000000000000000000..6a790dd51d232fbc556933a5e8173fbe6fa452fe --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsConnected.swift @@ -0,0 +1,25 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerIsConnected { + public var run: () -> Bool + + public func callAsFunction() -> Bool { + run() + } +} + +extension MessengerIsConnected { + public static func live(_ env: MessengerEnvironment) -> MessengerIsConnected { + MessengerIsConnected { + env.ctx.e2e != nil + } + } +} + +extension MessengerIsConnected { + public static let unimplemented = MessengerIsConnected( + run: XCTUnimplemented() + ) +} + diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerIsCreated.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsCreated.swift new file mode 100644 index 0000000000000000000000000000000000000000..cf7f5a4f6da8d00d7d306c55e82a28b7cbf73d69 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsCreated.swift @@ -0,0 +1,24 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerIsCreated { + public var run: () -> Bool + + public func callAsFunction() -> Bool { + run() + } +} + +extension MessengerIsCreated { + public static func live(_ env: MessengerEnvironment) -> MessengerIsCreated { + MessengerIsCreated { + env.fileManager.isDirectoryEmpty(env.storageDir()) == false + } + } +} + +extension MessengerIsCreated { + public static let unimplemented = MessengerIsCreated( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoaded.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoaded.swift new file mode 100644 index 0000000000000000000000000000000000000000..88750885c657d6e15fc7ecbc23e1e230a60b4845 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoaded.swift @@ -0,0 +1,24 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerIsLoaded { + public var run: () -> Bool + + public func callAsFunction() -> Bool { + run() + } +} + +extension MessengerIsLoaded { + public static func live(_ env: MessengerEnvironment) -> MessengerIsLoaded { + MessengerIsLoaded { + env.ctx.cMix != nil + } + } +} + +extension MessengerIsLoaded { + public static let unimplemented = MessengerIsLoaded( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoggedIn.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoggedIn.swift new file mode 100644 index 0000000000000000000000000000000000000000..7f886bef096f578931834f01aaead0e0cb6f2c36 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsLoggedIn.swift @@ -0,0 +1,24 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerIsLoggedIn { + public var run: () -> Bool + + public func callAsFunction() -> Bool { + run() + } +} + +extension MessengerIsLoggedIn { + public static func live(_ env: MessengerEnvironment) -> MessengerIsLoggedIn { + MessengerIsLoggedIn { + env.ctx.ud != nil + } + } +} + +extension MessengerIsLoggedIn { + public static let unimplemented = MessengerIsLoggedIn( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerIsRegistered.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsRegistered.swift new file mode 100644 index 0000000000000000000000000000000000000000..c91db5acb557b3a46c163dcacd44cb59a60d8c48 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerIsRegistered.swift @@ -0,0 +1,31 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerIsRegistered { + public enum Error: Swift.Error, Equatable { + case notConnected + } + + public var run: () throws -> Bool + + public func callAsFunction() throws -> Bool { + try run() + } +} + +extension MessengerIsRegistered { + public static func live(_ env: MessengerEnvironment) -> MessengerIsRegistered { + MessengerIsRegistered { + guard let e2e = env.ctx.e2e else { + throw Error.notConnected + } + return try env.isRegisteredWithUD(e2eId: e2e.getId()) + } + } +} + +extension MessengerIsRegistered { + public static let unimplemented = MessengerIsRegistered( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerLoad.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerLoad.swift new file mode 100644 index 0000000000000000000000000000000000000000..9b0454a4ee689c5590ea9823420cc03500b4b0c6 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerLoad.swift @@ -0,0 +1,28 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerLoad { + public var run: () throws -> Void + + public func callAsFunction() throws { + try run() + } +} + +extension MessengerLoad { + public static func live(_ env: MessengerEnvironment) -> MessengerLoad { + MessengerLoad { + env.ctx.cMix = try env.loadCMix( + storageDir: env.storageDir(), + password: try env.passwordStorage.load(), + cMixParamsJSON: env.getCMixParams() + ) + } + } +} + +extension MessengerLoad { + public static let unimplemented = MessengerLoad( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerLogIn.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerLogIn.swift new file mode 100644 index 0000000000000000000000000000000000000000..4b43a56b24f14887217ede4513b815b1cd970920 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerLogIn.swift @@ -0,0 +1,50 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerLogIn { + public enum Error: Swift.Error, Equatable { + case notLoaded + case notConnected + } + + public var run: () throws -> Void + + public func callAsFunction() throws { + try run() + } +} + +extension MessengerLogIn { + public static func live(_ env: MessengerEnvironment) -> MessengerLogIn { + MessengerLogIn { + guard let cMix = env.ctx.cMix else { + throw Error.notLoaded + } + guard let e2e = env.ctx.e2e else { + throw Error.notConnected + } + if cMix.networkFollowerStatus() != .running { + try cMix.startNetworkFollower(timeoutMS: 30_000) + } + env.ctx.ud = try env.newOrLoadUd( + params: .init( + e2eId: e2e.getId(), + username: nil, + registrationValidationSignature: nil, + cert: env.udCert() ?? e2e.getUdCertFromNdf(), + contactFile: env.udContact() ?? (try e2e.getUdContactFromNdf()), + address: env.udAddress() ?? e2e.getUdAddressFromNdf() + ), + follower: .init { + cMix.networkFollowerStatus().rawValue + } + ) + } + } +} + +extension MessengerLogIn { + public static let unimplemented = MessengerLogIn( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Functors/MessengerRegister.swift b/Sources/XXMessengerClient/Messenger/Functors/MessengerRegister.swift new file mode 100644 index 0000000000000000000000000000000000000000..1440dd43f01f1c25765265a763ea0e5a45b31730 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Functors/MessengerRegister.swift @@ -0,0 +1,52 @@ +import XXClient +import XCTestDynamicOverlay + +public struct MessengerRegister { + public enum Error: Swift.Error, Equatable { + case notLoaded + case notConnected + } + + public var run: (String) throws -> Void + + public func callAsFunction( + username: String + ) throws { + try run(username) + } +} + +extension MessengerRegister { + public static func live(_ env: MessengerEnvironment) -> MessengerRegister { + MessengerRegister { username in + guard let cMix = env.ctx.cMix else { + throw Error.notLoaded + } + guard let e2e = env.ctx.e2e else { + throw Error.notConnected + } + if cMix.networkFollowerStatus() != .running { + try cMix.startNetworkFollower(timeoutMS: 30_000) + } + env.ctx.ud = try env.newOrLoadUd( + params: .init( + e2eId: e2e.getId(), + username: username, + registrationValidationSignature: cMix.getReceptionRegistrationValidationSignature(), + cert: env.udCert() ?? e2e.getUdCertFromNdf(), + contactFile: env.udContact() ?? (try e2e.getUdContactFromNdf()), + address: env.udAddress() ?? e2e.getUdAddressFromNdf() + ), + follower: .init { + cMix.networkFollowerStatus().rawValue + } + ) + } + } +} + +extension MessengerRegister { + public static let unimplemented = MessengerRegister( + run: XCTUnimplemented() + ) +} diff --git a/Sources/XXMessengerClient/Messenger/Messenger.swift b/Sources/XXMessengerClient/Messenger/Messenger.swift new file mode 100644 index 0000000000000000000000000000000000000000..a477f7cc90ec06841b3d8820c28f8ed6eeaea9f8 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/Messenger.swift @@ -0,0 +1,46 @@ +import XXClient + +public struct Messenger { + public var isCreated: MessengerIsCreated + public var create: MessengerCreate + public var isLoaded: MessengerIsLoaded + public var load: MessengerLoad + public var isConnected: MessengerIsConnected + public var connect: MessengerConnect + public var isRegistered: MessengerIsRegistered + public var register: MessengerRegister + public var isLoggedIn: MessengerIsLoggedIn + public var logIn: MessengerLogIn +} + +extension Messenger { + public static func live(_ env: MessengerEnvironment) -> Messenger { + Messenger( + isCreated: .live(env), + create: .live(env), + isLoaded: .live(env), + load: .live(env), + isConnected: .live(env), + connect: .live(env), + isRegistered: .live(env), + register: .live(env), + isLoggedIn: .live(env), + logIn: .live(env) + ) + } +} + +extension Messenger { + public static let unimplemented = Messenger( + isCreated: .unimplemented, + create: .unimplemented, + isLoaded: .unimplemented, + load: .unimplemented, + isConnected: .unimplemented, + connect: .unimplemented, + isRegistered: .unimplemented, + register: .unimplemented, + isLoggedIn: .unimplemented, + logIn: .unimplemented + ) +} diff --git a/Sources/XXMessengerClient/Messenger/MessengerContext.swift b/Sources/XXMessengerClient/Messenger/MessengerContext.swift new file mode 100644 index 0000000000000000000000000000000000000000..ba67ed2b36b6674055120118f4c3060f50c15f44 --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/MessengerContext.swift @@ -0,0 +1,17 @@ +import XXClient + +public class MessengerContext { + public init( + cMix: CMix? = nil, + e2e: E2E? = nil, + ud: UserDiscovery? = nil + ) { + self.cMix = cMix + self.e2e = e2e + self.ud = ud + } + + public var cMix: CMix? + public var e2e: E2E? + public var ud: UserDiscovery? +} diff --git a/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift new file mode 100644 index 0000000000000000000000000000000000000000..dfa7dfcd3da15c9722d07349b306ba9b177ff39c --- /dev/null +++ b/Sources/XXMessengerClient/Messenger/MessengerEnvironment.swift @@ -0,0 +1,73 @@ +import Foundation +import XXClient +import XCTestDynamicOverlay + +public struct MessengerEnvironment { + public var ctx: MessengerContext + public var downloadNDF: DownloadAndVerifySignedNdf + public var fileManager: MessengerFileManager + public var generateSecret: GenerateSecret + public var getCMixParams: GetCMixParams + public var getE2EParams: GetE2EParams + public var isRegisteredWithUD: IsRegisteredWithUD + public var loadCMix: LoadCMix + public var login: Login + public var ndfEnvironment: NDFEnvironment + public var newCMix: NewCMix + public var newOrLoadUd: NewOrLoadUd + public var passwordStorage: PasswordStorage + public var storageDir: () -> String + public var udAddress: () -> String? + public var udCert: () -> Data? + public var udContact: () -> Data? +} + +extension MessengerEnvironment { + public static let defaultStorageDir = FileManager.default + .urls(for: .applicationSupportDirectory, in: .userDomainMask) + .first! + .appendingPathComponent("xx.network.client") + .path + + public static let live = MessengerEnvironment( + ctx: .init(), + downloadNDF: .live, + fileManager: .live(), + generateSecret: .live, + getCMixParams: .liveDefault, + getE2EParams: .liveDefault, + isRegisteredWithUD: .live, + loadCMix: .live, + login: .live, + ndfEnvironment: .mainnet, + newCMix: .live, + newOrLoadUd: .live, + passwordStorage: .keychain, + storageDir: { MessengerEnvironment.defaultStorageDir }, + udAddress: { nil }, + udCert: { nil }, + udContact: { nil } + ) +} + +extension MessengerEnvironment { + public static let unimplemented = MessengerEnvironment( + ctx: .init(), + downloadNDF: .unimplemented, + fileManager: .unimplemented, + generateSecret: .unimplemented, + getCMixParams: .unimplemented, + getE2EParams: .unimplemented, + isRegisteredWithUD: .unimplemented, + loadCMix: .unimplemented, + login: .unimplemented, + ndfEnvironment: .unimplemented, + newCMix: .unimplemented, + newOrLoadUd: .unimplemented, + passwordStorage: .unimplemented, + storageDir: XCTUnimplemented("\(Self.self).storageDir", placeholder: ""), + udAddress: XCTUnimplemented("\(Self.self).udAddress", placeholder: nil), + udCert: XCTUnimplemented("\(Self.self).udCert", placeholder: nil), + udContact: XCTUnimplemented("\(Self.self).udContact", placeholder: nil) + ) +} diff --git a/Sources/XXMessengerClient/Unimplemented.swift b/Sources/XXMessengerClient/Unimplemented.swift deleted file mode 100644 index 9454b9d77e43e6208b27e1a82464ffaee4378ba6..0000000000000000000000000000000000000000 --- a/Sources/XXMessengerClient/Unimplemented.swift +++ /dev/null @@ -1 +0,0 @@ -private enum Unimplemented {} diff --git a/Sources/XXMessengerClient/Utils/MessengerFileManager.swift b/Sources/XXMessengerClient/Utils/MessengerFileManager.swift new file mode 100644 index 0000000000000000000000000000000000000000..4ff49c5fe155e612852860d1d7276124729017d3 --- /dev/null +++ b/Sources/XXMessengerClient/Utils/MessengerFileManager.swift @@ -0,0 +1,40 @@ +import Foundation +import XCTestDynamicOverlay + +public struct MessengerFileManager { + public var isDirectoryEmpty: (String) -> Bool + public var removeDirectory: (String) throws -> Void + public var createDirectory: (String) throws -> Void +} + +extension MessengerFileManager { + public static func live( + fileManager: FileManager = .default + ) -> MessengerFileManager { + MessengerFileManager( + isDirectoryEmpty: { path in + let contents = try? fileManager.contentsOfDirectory(atPath: path) + return contents?.isEmpty ?? true + }, + removeDirectory: { path in + if fileManager.fileExists(atPath: path) { + try fileManager.removeItem(atPath: path) + } + }, + createDirectory: { path in + try fileManager.createDirectory( + atPath: path, + withIntermediateDirectories: true + ) + } + ) + } +} + +extension MessengerFileManager { + public static let unimplemented = MessengerFileManager( + isDirectoryEmpty: XCTUnimplemented("\(Self.self).isDirectoryEmpty"), + removeDirectory: XCTUnimplemented("\(Self.self).removeDirectory"), + createDirectory: XCTUnimplemented("\(Self.self).createDirectory") + ) +} diff --git a/Sources/XXMessengerClient/Utils/PasswordStorage+Keychain.swift b/Sources/XXMessengerClient/Utils/PasswordStorage+Keychain.swift new file mode 100644 index 0000000000000000000000000000000000000000..0a062cc628cf037491a37ba8639e1f2529f209e8 --- /dev/null +++ b/Sources/XXMessengerClient/Utils/PasswordStorage+Keychain.swift @@ -0,0 +1,21 @@ +import KeychainAccess +import XXClient + +extension PasswordStorage { + public static let keychain: PasswordStorage = { + let keychain = KeychainAccess.Keychain( + service: "xx.network.client.messenger" + ) + return PasswordStorage( + save: { password in + keychain[data: "password"] = password + }, + load: { + guard let password = keychain[data: "password"] else { + throw MissingPasswordError() + } + return password + } + ) + }() +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerConnectTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerConnectTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..c44b4907449a0ba57507a7e92575b69091dd8b04 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerConnectTests.swift @@ -0,0 +1,107 @@ +import CustomDump +import XXClient +import XCTest +@testable import XXMessengerClient + +final class MessengerConnectTests: XCTestCase { + func testConnect() throws { + struct DidLogIn: Equatable { + var ephemeral: Bool + var cMixId: Int + var authCallbacksProvided: Bool + var identity: ReceptionIdentity + var e2eParamsJSON: Data + } + var didLogIn: [DidLogIn] = [] + + let cMixId = 1234 + let receptionId = ReceptionIdentity.stub + let e2eParams = "e2e-params".data(using: .utf8)! + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.getId.run = { cMixId } + env.ctx.cMix!.makeLegacyReceptionIdentity.run = { receptionId } + env.getE2EParams.run = { e2eParams } + env.login.run = { ephemeral, cMixId, authCallbacks, identity, e2eParamsJSON in + didLogIn.append(.init( + ephemeral: ephemeral, + cMixId: cMixId, + authCallbacksProvided: authCallbacks != nil, + identity: identity, + e2eParamsJSON: e2eParamsJSON + )) + return .unimplemented + } + let connect: MessengerConnect = .live(env) + + try connect() + + XCTAssertNoDifference(didLogIn, [ + DidLogIn( + ephemeral: false, + cMixId: 1234, + authCallbacksProvided: false, + identity: .stub, + e2eParamsJSON: e2eParams + ) + ]) + + XCTAssertNotNil(env.ctx.e2e) + } + + func testConnectWithoutCMix() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + let connect: MessengerConnect = .live(env) + + XCTAssertThrowsError(try connect()) { error in + XCTAssertEqual( + error as? MessengerConnect.Error, + MessengerConnect.Error.notLoaded + ) + } + } + + func testMakeLegacyReceptionIdentityFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.getId.run = { 1234 } + env.ctx.cMix!.makeLegacyReceptionIdentity.run = { throw error } + let connect: MessengerConnect = .live(env) + + XCTAssertThrowsError(try connect()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testLoginFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.getId.run = { 1234 } + env.ctx.cMix!.makeLegacyReceptionIdentity.run = { .stub } + env.getE2EParams.run = { "e2e-params".data(using: .utf8)! } + env.login.run = { _, _, _, _, _ in throw error } + let connect: MessengerConnect = .live(env) + + XCTAssertThrowsError(try connect()) { err in + XCTAssertEqual(err as? Error, error) + } + } +} + +private extension ReceptionIdentity { + static let stub = ReceptionIdentity( + id: "id".data(using: .utf8)!, + rsaPrivatePem: "rsaPrivatePem".data(using: .utf8)!, + salt: "salt".data(using: .utf8)!, + dhKeyPrivate: "dhKeyPrivate".data(using: .utf8)!, + e2eGrp: "e2eGrp".data(using: .utf8)! + ) +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerCreateTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerCreateTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..5db87012a6b984e3db1ed3cb018e2cda96038d60 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerCreateTests.swift @@ -0,0 +1,159 @@ +import XCTest +import XXClient +@testable import XXMessengerClient +import CustomDump + +final class MessengerCreateTests: XCTestCase { + func testCreate() throws { + struct DidNewCMix: Equatable { + var ndfJSON: String + var storageDir: String + var password: Data + var registrationCode: String? + } + + var didDownloadNDF: [NDFEnvironment] = [] + var didGenerateSecret: [Int] = [] + var didSavePassword: [Data] = [] + var didRemoveDirectory: [String] = [] + var didCreateDirectory: [String] = [] + var didNewCMix: [DidNewCMix] = [] + + let ndf = "ndf".data(using: .utf8)! + let password = "password".data(using: .utf8)! + let storageDir = "storage-dir" + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { ndfEnvironment in + didDownloadNDF.append(ndfEnvironment) + return ndf + } + env.generateSecret.run = { numBytes in + didGenerateSecret.append(numBytes) + return password + } + env.passwordStorage.save = { password in + didSavePassword.append(password) + } + env.storageDir = { + storageDir + } + env.fileManager.removeDirectory = { path in + didRemoveDirectory.append(path) + } + env.fileManager.createDirectory = { path in + didCreateDirectory.append(path) + } + env.newCMix.run = { ndfJSON, storageDir, password, registrationCode in + didNewCMix.append(.init( + ndfJSON: ndfJSON, + storageDir: storageDir, + password: password, + registrationCode: registrationCode + )) + } + let create: MessengerCreate = .live(env) + + try create() + + XCTAssertNoDifference(didDownloadNDF, [.unimplemented]) + XCTAssertNoDifference(didGenerateSecret, [32]) + XCTAssertNoDifference(didSavePassword, [password]) + XCTAssertNoDifference(didRemoveDirectory, [storageDir]) + XCTAssertNoDifference(didCreateDirectory, [storageDir]) + XCTAssertNoDifference(didNewCMix, [.init( + ndfJSON: String(data: ndf, encoding: .utf8)!, + storageDir: storageDir, + password: password, + registrationCode: nil + )]) + } + + func testDownloadNDFFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { _ in throw error } + let create: MessengerCreate = .live(env) + + XCTAssertThrowsError(try create()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testSavePasswordFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { _ in "ndf".data(using: .utf8)! } + env.generateSecret.run = { _ in "password".data(using: .utf8)! } + env.passwordStorage.save = { _ in throw error } + let create: MessengerCreate = .live(env) + + XCTAssertThrowsError(try create()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testRemoveDirectoryFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { _ in "ndf".data(using: .utf8)! } + env.generateSecret.run = { _ in "password".data(using: .utf8)! } + env.passwordStorage.save = { _ in } + env.storageDir = { "storage-dir" } + env.fileManager.removeDirectory = { _ in throw error } + let create: MessengerCreate = .live(env) + + XCTAssertThrowsError(try create()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testCreateDirectoryFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { _ in "ndf".data(using: .utf8)! } + env.generateSecret.run = { _ in "password".data(using: .utf8)! } + env.passwordStorage.save = { _ in } + env.storageDir = { "storage-dir" } + env.fileManager.removeDirectory = { _ in } + env.fileManager.createDirectory = { _ in throw error } + let create: MessengerCreate = .live(env) + + XCTAssertThrowsError(try create()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testNewCMixFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ndfEnvironment = .unimplemented + env.downloadNDF.run = { _ in "ndf".data(using: .utf8)! } + env.generateSecret.run = { _ in "password".data(using: .utf8)! } + env.passwordStorage.save = { _ in } + env.storageDir = { "storage-dir" } + env.fileManager.removeDirectory = { _ in } + env.fileManager.createDirectory = { _ in } + env.newCMix.run = { _, _, _, _ in throw error } + let create: MessengerCreate = .live(env) + + XCTAssertThrowsError(try create()) { err in + XCTAssertEqual(err as? Error, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsConnectedTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsConnectedTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..e207e8a5d2eaca4c25f4c286d95bf991f20a270c --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsConnectedTests.swift @@ -0,0 +1,20 @@ +import XCTest +@testable import XXMessengerClient + +final class MessengerIsConnectedTests: XCTestCase { + func testWithE2E() { + let env: MessengerEnvironment = .unimplemented + env.ctx.e2e = .unimplemented + let isConnected: MessengerIsConnected = .live(env) + + XCTAssertTrue(isConnected()) + } + + func testWithoutE2E() { + let env: MessengerEnvironment = .unimplemented + env.ctx.e2e = nil + let isConnected: MessengerIsConnected = .live(env) + + XCTAssertFalse(isConnected()) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsCreatedTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsCreatedTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..a96c8a6073b8e34b3d5553628657d2d9cec0632e --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsCreatedTests.swift @@ -0,0 +1,37 @@ +import CustomDump +import XCTest +@testable import XXMessengerClient + +final class MessengerIsCreatedTests: XCTestCase { + func testStorageDirNotEmpty() { + var didIsDirectoryEmpty: [String] = [] + let storageDir = "storage-dir" + + var env: MessengerEnvironment = .unimplemented + env.storageDir = { storageDir } + env.fileManager.isDirectoryEmpty = { path in + didIsDirectoryEmpty.append(path) + return false + } + let isCreated: MessengerIsCreated = .live(env) + + XCTAssertTrue(isCreated()) + XCTAssertNoDifference(didIsDirectoryEmpty, [storageDir]) + } + + func testStorageDirEmpty() { + var didIsDirectoryEmpty: [String] = [] + let storageDir = "storage-dir" + + var env: MessengerEnvironment = .unimplemented + env.storageDir = { storageDir } + env.fileManager.isDirectoryEmpty = { path in + didIsDirectoryEmpty.append(path) + return true + } + let isCreated: MessengerIsCreated = .live(env) + + XCTAssertFalse(isCreated()) + XCTAssertNoDifference(didIsDirectoryEmpty, [storageDir]) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoadedTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoadedTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..c83dc523f99e1049feea566ca6772a31394ea097 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoadedTests.swift @@ -0,0 +1,20 @@ +import XCTest +@testable import XXMessengerClient + +final class MessengerIsLoadedTests: XCTestCase { + func testWithCMix() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + let isLoaded: MessengerIsLoaded = .live(env) + + XCTAssertTrue(isLoaded()) + } + + func testWithoutCMix() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + let isLoaded: MessengerIsLoaded = .live(env) + + XCTAssertFalse(isLoaded()) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoggedInTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoggedInTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..6b5b79034acce19387e150bd8bc6c84c6c61ea0e --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsLoggedInTests.swift @@ -0,0 +1,20 @@ +import XCTest +@testable import XXMessengerClient + +final class MessengerIsLoggedInTests: XCTestCase { + func testWithUD() { + let env: MessengerEnvironment = .unimplemented + env.ctx.ud = .unimplemented + let isLoggedIn: MessengerIsLoggedIn = .live(env) + + XCTAssertTrue(isLoggedIn()) + } + + func testWithoutUD() { + let env: MessengerEnvironment = .unimplemented + env.ctx.ud = nil + let isLoggedIn: MessengerIsLoggedIn = .live(env) + + XCTAssertFalse(isLoggedIn()) + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsRegisteredTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsRegisteredTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..250fdad884357e6cb4a7012a845c8bb37a000381 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerIsRegisteredTests.swift @@ -0,0 +1,58 @@ +import XCTest +@testable import XXMessengerClient + +final class MessengerIsRegisteredTests: XCTestCase { + func testRegistered() throws { + var didIsRegisteredWithUD: [Int] = [] + + var env: MessengerEnvironment = .unimplemented + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.isRegisteredWithUD.run = { e2eId in + didIsRegisteredWithUD.append(e2eId) + return true + } + let isRegistered: MessengerIsRegistered = .live(env) + + XCTAssertTrue(try isRegistered()) + XCTAssertEqual(didIsRegisteredWithUD, [1234]) + } + + func testNotRegistered() throws { + var env: MessengerEnvironment = .unimplemented + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.isRegisteredWithUD.run = { _ in false } + let isRegistered: MessengerIsRegistered = .live(env) + + XCTAssertFalse(try isRegistered()) + } + + func testWithoutE2E() { + let env: MessengerEnvironment = .unimplemented + env.ctx.e2e = nil + let isRegistered: MessengerIsRegistered = .live(env) + + XCTAssertThrowsError(try isRegistered()) { err in + XCTAssertEqual( + err as? MessengerIsRegistered.Error, + MessengerIsRegistered.Error.notConnected + ) + } + } + + func testIsRegisteredWithUDFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.isRegisteredWithUD.run = { _ in throw error } + let isRegistered: MessengerIsRegistered = .live(env) + + XCTAssertThrowsError(try isRegistered()) { err in + XCTAssertEqual(err as? Error, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLoadTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLoadTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..ef5694c2a8cb0b47e227154bc1d54d6c06dceca8 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLoadTests.swift @@ -0,0 +1,77 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerLoadTests: XCTestCase { + func testLoad() throws { + struct DidLoadCMix: Equatable { + var storageDir: String + var password: Data + var cMixParamsJSON: Data + } + var didLoadCMix: [DidLoadCMix] = [] + + let storageDir = "test-storage-dir" + let password = "password".data(using: .utf8)! + let cMixParams = "cmix-params".data(using: .utf8)! + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + env.storageDir = { storageDir } + env.passwordStorage.load = { password } + env.getCMixParams.run = { cMixParams } + env.loadCMix.run = { storageDir, password, cMixParamsJSON in + didLoadCMix.append(.init( + storageDir: storageDir, + password: password, + cMixParamsJSON: cMixParamsJSON + )) + return .unimplemented + } + let load: MessengerLoad = .live(env) + + try load() + + XCTAssertNoDifference(didLoadCMix, [ + DidLoadCMix( + storageDir: storageDir, + password: password, + cMixParamsJSON: cMixParams + ) + ]) + XCTAssertNotNil(env.ctx.cMix) + } + + func testMissingPassword() { + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + env.storageDir = { "storage-dir" } + env.passwordStorage.load = { throw PasswordStorage.MissingPasswordError() } + let load: MessengerLoad = .live(env) + + XCTAssertThrowsError(try load()) { err in + XCTAssertEqual( + err as? PasswordStorage.MissingPasswordError, + PasswordStorage.MissingPasswordError() + ) + } + } + + func testLoadCMixFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + env.storageDir = { "storage-dir" } + env.passwordStorage.load = { "password".data(using: .utf8)! } + env.getCMixParams.run = { "cmix-params".data(using: .utf8)! } + env.loadCMix.run = { _, _, _ in throw error } + let load: MessengerLoad = .live(env) + + XCTAssertThrowsError(try load()) { err in + XCTAssertEqual(err as? Error, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLogInTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLogInTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..92e511f2de3212091e85bd2b6e184d83d0740645 --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerLogInTests.swift @@ -0,0 +1,171 @@ +import XCTest +import XXClient +@testable import XXMessengerClient +import CustomDump + +final class MessengerLogInTests: XCTestCase { + func testLogin() throws { + var didStartNetworkFollower: [Int] = [] + var didNewOrLoadUDWithParams: [NewOrLoadUd.Params] = [] + var didNewOrLoadUDWithFollower: [UdNetworkStatus] = [] + + let e2eId = 1234 + let networkFollowerStatus: NetworkFollowerStatus = .stopped + let udCertFromNDF = "ndf-ud-cert".data(using: .utf8)! + let udContactFromNDF = "ndf-ud-contact".data(using: .utf8)! + let udAddressFromNDF = "ndf-ud-address" + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { networkFollowerStatus } + env.ctx.cMix!.startNetworkFollower.run = { timeout in + didStartNetworkFollower.append(timeout) + } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { e2eId } + env.udCert = { nil } + env.udContact = { nil } + env.udAddress = { nil } + env.ctx.e2e!.getUdCertFromNdf.run = { udCertFromNDF } + env.ctx.e2e!.getUdContactFromNdf.run = { udContactFromNDF } + env.ctx.e2e!.getUdAddressFromNdf.run = { udAddressFromNDF } + env.newOrLoadUd.run = { params, follower in + didNewOrLoadUDWithParams.append(params) + didNewOrLoadUDWithFollower.append(follower) + return .unimplemented + } + let logIn: MessengerLogIn = .live(env) + try logIn() + + XCTAssertEqual(didStartNetworkFollower, [30_000]) + XCTAssertNoDifference(didNewOrLoadUDWithParams, [.init( + e2eId: e2eId, + username: nil, + registrationValidationSignature: nil, + cert: udCertFromNDF, + contactFile: udContactFromNDF, + address: udAddressFromNDF + )]) + XCTAssertEqual(didNewOrLoadUDWithFollower.count, 1) + XCTAssertEqual( + didNewOrLoadUDWithFollower.first?.handle(), + networkFollowerStatus.rawValue + ) + XCTAssertNotNil(env.ctx.ud) + } + + func testLoginWithAlternativeUD() throws { + var didNewOrLoadUDWithParams: [NewOrLoadUd.Params] = [] + let e2eId = 1234 + let altUdCert = "alt-ud-cert".data(using: .utf8)! + let altUdContact = "alt-ud-contact".data(using: .utf8)! + let altUdAddress = "alt-ud-address" + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { e2eId } + env.udCert = { altUdCert } + env.udContact = { altUdContact } + env.udAddress = { altUdAddress } + env.newOrLoadUd.run = { params, _ in + didNewOrLoadUDWithParams.append(params) + return .unimplemented + } + let logIn: MessengerLogIn = .live(env) + try logIn() + + XCTAssertNoDifference(didNewOrLoadUDWithParams, [.init( + e2eId: e2eId, + username: nil, + registrationValidationSignature: nil, + cert: altUdCert, + contactFile: altUdContact, + address: altUdAddress + )]) + XCTAssertNotNil(env.ctx.ud) + } + + func testLoginWithoutCMix() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + let logIn: MessengerLogIn = .live(env) + + XCTAssertThrowsError(try logIn()) { error in + XCTAssertEqual( + error as? MessengerLogIn.Error, + MessengerLogIn.Error.notLoaded + ) + } + } + + func testLoginWithoutE2E() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.e2e = nil + let logIn: MessengerLogIn = .live(env) + + XCTAssertThrowsError(try logIn()) { error in + XCTAssertEqual( + error as? MessengerLogIn.Error, + MessengerLogIn.Error.notConnected + ) + } + } + + func testStartNetworkFollowerFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .stopped } + env.ctx.cMix!.startNetworkFollower.run = { _ in throw error } + let logIn: MessengerLogIn = .live(env) + + XCTAssertThrowsError(try logIn()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testGetUdContactFromNdfFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.udCert = { nil } + env.udContact = { nil } + env.ctx.e2e!.getUdCertFromNdf.run = { "ndf-ud-cert".data(using: .utf8)! } + env.ctx.e2e!.getUdContactFromNdf.run = { throw error } + let logIn: MessengerLogIn = .live(env) + + XCTAssertThrowsError(try logIn()) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testNewOrLoadUdFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.udCert = { "ud-cert".data(using: .utf8)! } + env.udContact = { "ud-contact".data(using: .utf8)! } + env.udAddress = { "ud-address" } + env.newOrLoadUd.run = { _, _ in throw error } + let logIn: MessengerLogIn = .live(env) + + XCTAssertThrowsError(try logIn()) { err in + XCTAssertEqual(err as? Error, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/Messenger/Functors/MessengerRegisterTests.swift b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerRegisterTests.swift new file mode 100644 index 0000000000000000000000000000000000000000..deb6a8dcfd209e99404b092033e870d42e13305b --- /dev/null +++ b/Tests/XXMessengerClientTests/Messenger/Functors/MessengerRegisterTests.swift @@ -0,0 +1,188 @@ +import CustomDump +import XCTest +import XXClient +@testable import XXMessengerClient + +final class MessengerRegisterTests: XCTestCase { + func testRegister() throws { + var didStartNetworkFollower: [Int] = [] + var didNewOrLoadUDWithParams: [NewOrLoadUd.Params] = [] + var didNewOrLoadUDWithFollower: [UdNetworkStatus] = [] + + let e2eId = 1234 + let networkFollowerStatus: NetworkFollowerStatus = .stopped + let registrationSignature = "registration-signature".data(using: .utf8)! + let udCertFromNDF = "ndf-ud-cert".data(using: .utf8)! + let udContactFromNDF = "ndf-ud-contact".data(using: .utf8)! + let udAddressFromNDF = "ndf-ud-address" + let username = "new-user-name" + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { networkFollowerStatus } + env.ctx.cMix!.startNetworkFollower.run = { timeout in + didStartNetworkFollower.append(timeout) + } + env.ctx.cMix!.getReceptionRegistrationValidationSignature.run = { + registrationSignature + } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { e2eId } + env.udCert = { nil } + env.udContact = { nil } + env.udAddress = { nil } + env.ctx.e2e!.getUdCertFromNdf.run = { udCertFromNDF } + env.ctx.e2e!.getUdContactFromNdf.run = { udContactFromNDF } + env.ctx.e2e!.getUdAddressFromNdf.run = { udAddressFromNDF } + env.newOrLoadUd.run = { params, follower in + didNewOrLoadUDWithParams.append(params) + didNewOrLoadUDWithFollower.append(follower) + return .unimplemented + } + let register: MessengerRegister = .live(env) + try register(username: username) + + XCTAssertEqual(didStartNetworkFollower, [30_000]) + XCTAssertNoDifference(didNewOrLoadUDWithParams, [.init( + e2eId: e2eId, + username: username, + registrationValidationSignature: registrationSignature, + cert: udCertFromNDF, + contactFile: udContactFromNDF, + address: udAddressFromNDF + )]) + XCTAssertEqual(didNewOrLoadUDWithFollower.count, 1) + XCTAssertEqual( + didNewOrLoadUDWithFollower.first?.handle(), + networkFollowerStatus.rawValue + ) + XCTAssertNotNil(env.ctx.ud) + } + + func testRegisterWithAlternativeUD() throws { + var didNewOrLoadUDWithParams: [NewOrLoadUd.Params] = [] + let e2eId = 1234 + let registrationSignature = "registration-signature".data(using: .utf8)! + let altUdCert = "alt-ud-cert".data(using: .utf8)! + let altUdContact = "alt-ud-contact".data(using: .utf8)! + let altUdAddress = "alt-ud-address" + let username = "new-user-name" + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.cMix!.getReceptionRegistrationValidationSignature.run = { + registrationSignature + } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { e2eId } + env.udCert = { altUdCert } + env.udContact = { altUdContact } + env.udAddress = { altUdAddress } + env.newOrLoadUd.run = { params, _ in + didNewOrLoadUDWithParams.append(params) + return .unimplemented + } + let register: MessengerRegister = .live(env) + try register(username: username) + + XCTAssertNoDifference(didNewOrLoadUDWithParams, [.init( + e2eId: e2eId, + username: username, + registrationValidationSignature: registrationSignature, + cert: altUdCert, + contactFile: altUdContact, + address: altUdAddress + )]) + XCTAssertNotNil(env.ctx.ud) + } + + func testRegisterWithoutCMix() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = nil + let register: MessengerRegister = .live(env) + + XCTAssertThrowsError(try register(username: "new-user-name")) { error in + XCTAssertEqual( + error as? MessengerRegister.Error, + MessengerRegister.Error.notLoaded + ) + } + } + + func testRegisterWithoutE2E() { + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.e2e = nil + let register: MessengerRegister = .live(env) + + XCTAssertThrowsError(try register(username: "new-user-name")) { error in + XCTAssertEqual( + error as? MessengerRegister.Error, + MessengerRegister.Error.notConnected + ) + } + } + + func testStartNetworkFollowerFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + let env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .stopped } + env.ctx.cMix!.startNetworkFollower.run = { _ in throw error } + env.ctx.e2e = .unimplemented + let register: MessengerRegister = .live(env) + + XCTAssertThrowsError(try register(username: "new-user-name")) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testGetUdContactFromNdfFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.cMix!.getReceptionRegistrationValidationSignature.run = { + "registration-signature".data(using: .utf8)! + } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.udCert = { nil } + env.udContact = { nil } + env.ctx.e2e!.getUdCertFromNdf.run = { "ndf-ud-cert".data(using: .utf8)! } + env.ctx.e2e!.getUdContactFromNdf.run = { throw error } + let register: MessengerRegister = .live(env) + + XCTAssertThrowsError(try register(username: "new-user-name")) { err in + XCTAssertEqual(err as? Error, error) + } + } + + func testNewOrLoadUdFailure() { + struct Error: Swift.Error, Equatable {} + let error = Error() + + var env: MessengerEnvironment = .unimplemented + env.ctx.cMix = .unimplemented + env.ctx.cMix!.networkFollowerStatus.run = { .running } + env.ctx.cMix!.getReceptionRegistrationValidationSignature.run = { + "registration-signature".data(using: .utf8)! + } + env.ctx.e2e = .unimplemented + env.ctx.e2e!.getId.run = { 1234 } + env.udCert = { "ud-cert".data(using: .utf8)! } + env.udContact = { "ud-contact".data(using: .utf8)! } + env.udAddress = { "ud-address" } + env.newOrLoadUd.run = { _, _ in throw error } + let register: MessengerRegister = .live(env) + + XCTAssertThrowsError(try register(username: "new-user-name")) { err in + XCTAssertEqual(err as? Error, error) + } + } +} diff --git a/Tests/XXMessengerClientTests/XXMessengerClientTests.swift b/Tests/XXMessengerClientTests/XXMessengerClientTests.swift deleted file mode 100644 index 11caac7a87166ce97667d9cefba7df1942839dd7..0000000000000000000000000000000000000000 --- a/Tests/XXMessengerClientTests/XXMessengerClientTests.swift +++ /dev/null @@ -1,8 +0,0 @@ -import XCTest -@testable import XXMessengerClient - -final class XXMessengerClientTests: XCTestCase { - func testExample() { - XCTAssert(true) - } -}