From cb7787002e2e0bf5059d5e84ef7436e01b1be2d0 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Sun, 16 Oct 2022 23:57:36 +0200 Subject: [PATCH] Implement MessengerReceiveFile function --- .../Functions/MessengerReceiveFile.swift | 71 +++++- .../Functions/MessengerReceiveFileTests.swift | 206 +++++++++++++++++- 2 files changed, 264 insertions(+), 13 deletions(-) diff --git a/Sources/XXMessengerClient/Messenger/Functions/MessengerReceiveFile.swift b/Sources/XXMessengerClient/Messenger/Functions/MessengerReceiveFile.swift index 91230c63..ef4290f8 100644 --- a/Sources/XXMessengerClient/Messenger/Functions/MessengerReceiveFile.swift +++ b/Sources/XXMessengerClient/Messenger/Functions/MessengerReceiveFile.swift @@ -3,24 +3,79 @@ import XCTestDynamicOverlay import XXClient public struct MessengerReceiveFile { + public struct Params: Equatable { + public init( + transferId: Data, + callbackIntervalMS: Int = 250 + ) { + self.transferId = transferId + self.callbackIntervalMS = callbackIntervalMS + } + + public var transferId: Data + public var callbackIntervalMS: Int + } + + public enum CallbackInfo: Equatable { + public enum Failure: Equatable { + case callbackError(NSError) + case progressError(String) + case receiveError(NSError) + } + + case progress(transmitted: Int, total: Int) + case finished(Data) + case failed(Failure) + } + + public typealias Callback = (CallbackInfo) -> Void + public enum Error: Swift.Error, Equatable { - case notConnected + case fileTransferNotStarted } - public var run: () throws -> Void + public var run: (Params, @escaping Callback) throws -> Void - public func callAsFunction() throws -> Void { - try run() + public func callAsFunction( + _ params: Params, + callback: @escaping Callback + ) throws -> Void { + try run(params, callback) } } extension MessengerReceiveFile { public static func live(_ env: MessengerEnvironment) -> MessengerReceiveFile { - MessengerReceiveFile { - guard let e2e = env.e2e() else { - throw Error.notConnected + MessengerReceiveFile { params, callback in + guard let fileTransfer = env.fileTransfer() else { + throw Error.fileTransferNotStarted } - // TODO: implement receiving file + try fileTransfer.registerReceivedProgressCallback( + transferId: params.transferId, + period: params.callbackIntervalMS, + callback: FileTransferProgressCallback { result in + switch result { + case .success(let info): + if let error = info.progress.error { + callback(.failed(.progressError(error))) + } else if info.progress.completed { + do { + callback(.finished(try fileTransfer.receive(transferId: params.transferId))) + } catch { + callback(.failed(.receiveError(error as NSError))) + } + } else { + callback(.progress( + transmitted: info.progress.transmitted, + total: info.progress.total + )) + } + + case .failure(let error): + callback(.failed(.callbackError(error))) + } + } + ) } } } diff --git a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerReceiveFileTests.swift b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerReceiveFileTests.swift index ef9b5864..554b7f30 100644 --- a/Tests/XXMessengerClientTests/Messenger/Functions/MessengerReceiveFileTests.swift +++ b/Tests/XXMessengerClientTests/Messenger/Functions/MessengerReceiveFileTests.swift @@ -5,23 +5,219 @@ import XXClient final class MessengerReceiveFileTests: XCTestCase { func testReceiveFile() throws { + let params: MessengerReceiveFile.Params = .stub + let receivedData = "received".data(using: .utf8)! + + var didRegisterReceivedProgressCallbackWithTransferId: [Data] = [] + var didRegisterReceivedProgressCallbackWithPeriod: [Int] = [] + var didRegisterReceivedProgressCallbackWithCallback: [FileTransferProgressCallback] = [] + var didReceiveTransferId: [Data] = [] + var didReceiveCallback: [MessengerReceiveFile.CallbackInfo] = [] + var env: MessengerEnvironment = .unimplemented - env.e2e.get = { .unimplemented } + env.fileTransfer.get = { + var fileTransfer: FileTransfer = .unimplemented + fileTransfer.registerReceivedProgressCallback.run = { transferId, period, callback in + didRegisterReceivedProgressCallbackWithTransferId.append(transferId) + didRegisterReceivedProgressCallbackWithPeriod.append(period) + didRegisterReceivedProgressCallbackWithCallback.append(callback) + } + fileTransfer.receive.run = { transferId in + didReceiveTransferId.append(transferId) + return receivedData + } + return fileTransfer + } let receiveFile: MessengerReceiveFile = .live(env) - try receiveFile() + try receiveFile(params) { info in + didReceiveCallback.append(info) + } + + XCTAssertNoDifference(didRegisterReceivedProgressCallbackWithTransferId, [ + params.transferId + ]) + XCTAssertNoDifference(didRegisterReceivedProgressCallbackWithPeriod, [ + params.callbackIntervalMS + ]) + XCTAssertNoDifference(didReceiveCallback, []) + + didReceiveCallback = [] + didRegisterReceivedProgressCallbackWithCallback.first?.handle(.success( + FileTransferProgressCallback.Callback( + progress: Progress( + completed: false, + transmitted: 1, + total: 3, + error: nil + ), + partTracker: .unimplemented + ) + )) + + XCTAssertNoDifference(didReceiveCallback, [ + .progress(transmitted: 1, total: 3), + ]) + + didReceiveCallback = [] + didRegisterReceivedProgressCallbackWithCallback.first?.handle(.success( + FileTransferProgressCallback.Callback( + progress: Progress( + completed: false, + transmitted: 2, + total: 3, + error: nil + ), + partTracker: .unimplemented + ) + )) + + XCTAssertNoDifference(didReceiveCallback, [ + .progress(transmitted: 2, total: 3), + ]) + + didReceiveCallback = [] + didRegisterReceivedProgressCallbackWithCallback.first?.handle(.success( + FileTransferProgressCallback.Callback( + progress: Progress( + completed: true, + transmitted: 3, + total: 3, + error: nil + ), + partTracker: .unimplemented + ) + )) + + XCTAssertNoDifference(didReceiveTransferId, [ + params.transferId, + ]) + XCTAssertNoDifference(didReceiveCallback, [ + .finished(receivedData), + ]) } func testReceiveFileWhenNotConnected() { var env: MessengerEnvironment = .unimplemented - env.e2e.get = { nil } + env.fileTransfer.get = { nil } let receiveFile: MessengerReceiveFile = .live(env) - XCTAssertThrowsError(try receiveFile()) { error in + XCTAssertThrowsError(try receiveFile(.stub) { _ in }) { error in XCTAssertNoDifference( error as? MessengerReceiveFile.Error, - MessengerReceiveFile.Error.notConnected + MessengerReceiveFile.Error.fileTransferNotStarted ) } } + + func testReceiveFileProgressError() throws { + let error = "Something went wrong..." + + var receivedProgressCallback: FileTransferProgressCallback? + var didReceiveCallback: [MessengerReceiveFile.CallbackInfo] = [] + + var env: MessengerEnvironment = .unimplemented + env.fileTransfer.get = { + var fileTransfer: FileTransfer = .unimplemented + fileTransfer.registerReceivedProgressCallback.run = { _, _, callback in + receivedProgressCallback = callback + } + return fileTransfer + } + let receiveFile: MessengerReceiveFile = .live(env) + + try receiveFile(.stub) { info in + didReceiveCallback.append(info) + } + + receivedProgressCallback?.handle(.success( + FileTransferProgressCallback.Callback( + progress: Progress( + completed: false, + transmitted: 1, + total: 3, + error: error + ), + partTracker: .unimplemented + ) + )) + + XCTAssertNoDifference(didReceiveCallback, [ + .failed(.progressError(error)) + ]) + } + + func testReceiveFileCallbackError() throws { + let error = NSError(domain: "test", code: 123) + + var receivedProgressCallback: FileTransferProgressCallback? + var didReceiveCallback: [MessengerReceiveFile.CallbackInfo] = [] + + var env: MessengerEnvironment = .unimplemented + env.fileTransfer.get = { + var fileTransfer: FileTransfer = .unimplemented + fileTransfer.registerReceivedProgressCallback.run = { _, _, callback in + receivedProgressCallback = callback + } + return fileTransfer + } + let receiveFile: MessengerReceiveFile = .live(env) + + try receiveFile(.stub) { info in + didReceiveCallback.append(info) + } + + receivedProgressCallback?.handle(.failure(error)) + + XCTAssertNoDifference(didReceiveCallback, [ + .failed(.callbackError(error)) + ]) + } + + func testReceiveFileReceiveError() throws { + let error = NSError(domain: "test", code: 123) + + var receivedProgressCallback: FileTransferProgressCallback? + var didReceiveCallback: [MessengerReceiveFile.CallbackInfo] = [] + + var env: MessengerEnvironment = .unimplemented + env.fileTransfer.get = { + var fileTransfer: FileTransfer = .unimplemented + fileTransfer.registerReceivedProgressCallback.run = { _, _, callback in + receivedProgressCallback = callback + } + fileTransfer.receive.run = { _ in + throw error + } + return fileTransfer + } + let receiveFile: MessengerReceiveFile = .live(env) + + try receiveFile(.stub) { info in + didReceiveCallback.append(info) + } + + receivedProgressCallback?.handle(.success( + FileTransferProgressCallback.Callback( + progress: Progress( + completed: true, + transmitted: 3, + total: 3, + error: nil + ), + partTracker: .unimplemented + ) + )) + + XCTAssertNoDifference(didReceiveCallback, [ + .failed(.receiveError(error)) + ]) + } +} + +private extension MessengerReceiveFile.Params { + static let stub = MessengerReceiveFile.Params( + transferId: "transfer-id".data(using: .utf8)!, + callbackIntervalMS: 123 + ) } -- GitLab