Skip to content
Snippets Groups Projects
Commit de1baeb1 authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Merge branch 'feature/messenger-send-file' into 'development'

Messenger send file

See merge request elixxir/elixxir-dapps-sdk-swift!122
parents 47b3ab24 8e15bc02
No related branches found
No related tags found
2 merge requests!122Messenger send file,!102Release 1.0.0
......@@ -3,6 +3,14 @@ import XCTestDynamicOverlay
public struct FileTransferProgressCallback {
public struct Callback {
public init(
progress: Progress,
partTracker: FilePartTracker
) {
self.progress = progress
self.partTracker = partTracker
}
public var progress: Progress
public var partTracker: FilePartTracker
}
......
......@@ -2,28 +2,40 @@ import Bindings
import XCTestDynamicOverlay
public struct InitFileTransfer {
public var run: (Int, Data, Data, ReceiveFileCallback) throws -> FileTransfer
public func callAsFunction(
public struct Params: Equatable {
public init(
e2eId: Int,
e2eFileTransferParamsJSON: Data = GetE2EFileTransferParams.liveDefault(),
fileTransferParamsJSON: Data = GetFileTransferParams.liveDefault(),
fileTransferParamsJSON: Data = GetFileTransferParams.liveDefault()
) {
self.e2eId = e2eId
self.e2eFileTransferParamsJSON = e2eFileTransferParamsJSON
self.fileTransferParamsJSON = fileTransferParamsJSON
}
public var e2eId: Int
public var e2eFileTransferParamsJSON: Data = GetE2EFileTransferParams.liveDefault()
public var fileTransferParamsJSON: Data = GetFileTransferParams.liveDefault()
}
public var run: (Params, ReceiveFileCallback) throws -> FileTransfer
public func callAsFunction(
params: Params,
callback: ReceiveFileCallback
) throws -> FileTransfer {
try run(e2eId, e2eFileTransferParamsJSON, fileTransferParamsJSON, callback)
try run(params, callback)
}
}
extension InitFileTransfer {
public static let live = InitFileTransfer {
e2eId, e2eFileTransferParamsJSON, fileTransferParamsJSON, callback in
public static let live = InitFileTransfer { params, callback in
var error: NSError?
let bindingsFileTransfer = BindingsInitFileTransfer(
e2eId,
params.e2eId,
callback.makeBindingsReceiveFileCallback(),
e2eFileTransferParamsJSON,
fileTransferParamsJSON,
params.e2eFileTransferParamsJSON,
params.fileTransferParamsJSON,
&error
)
if let error = error {
......
import Foundation
import XCTestDynamicOverlay
import XXClient
public struct MessengerSendFile {
public struct Params: Equatable {
public init(
file: FileSend,
recipientId: Data,
retry: Int = 3,
callbackIntervalMS: Int = 250
) {
self.file = file
self.recipientId = recipientId
self.retry = retry
self.callbackIntervalMS = callbackIntervalMS
}
public var file: FileSend
public var recipientId: Data
public var retry: Int
public var callbackIntervalMS: Int
}
public enum CallbackInfo: Equatable {
public enum Failure: Equatable {
case error(NSError)
case progressError(String)
case close(NSError)
}
case progress(id: Data, transmitted: Int, total: Int)
case finished(id: Data)
case failed(id: Data, Failure)
}
public typealias Callback = (CallbackInfo) -> Void
public enum Error: Swift.Error, Equatable {
case notConnected
}
public var run: (Params, @escaping Callback) throws -> Data
public func callAsFunction(
_ params: Params,
callback: @escaping Callback
) throws -> Data {
try run(params, callback)
}
}
extension MessengerSendFile {
public static func live(_ env: MessengerEnvironment) -> MessengerSendFile {
MessengerSendFile { params, callback in
guard let e2e = env.e2e() else {
throw Error.notConnected
}
let fileTransfer = try env.initFileTransfer(
params: InitFileTransfer.Params(
e2eId: e2e.getId(),
e2eFileTransferParamsJSON: env.getE2EFileTransferParams(),
fileTransferParamsJSON: env.getFileTransferParams()
),
callback: ReceiveFileCallback { _ in
fatalError("Bindings issue: ReceiveFileCallback called when sending file.")
}
)
func close(id: Data) {
do {
try fileTransfer.closeSend(transferId: id)
} catch {
callback(.failed(id: id, .close(error as NSError)))
}
}
var transferId: Data!
transferId = try fileTransfer.send(
params: FileTransferSend.Params(
payload: params.file,
recipientId: params.recipientId,
retry: Float(params.retry),
period: params.callbackIntervalMS
),
callback: FileTransferProgressCallback { result in
guard let transferId else {
fatalError("Bindings issue: file transfer progress callback was called before send function returned transfer id.")
}
switch result {
case .failure(let error):
callback(.failed(id: transferId, .error(error)))
close(id: transferId)
case .success(let cb):
if let error = cb.progress.error {
callback(.failed(id: transferId, .progressError(error)))
close(id: transferId)
} else if cb.progress.completed {
callback(.finished(id: transferId))
close(id: transferId)
} else {
callback(.progress(
id: transferId,
transmitted: cb.progress.transmitted,
total: cb.progress.total
))
}
}
}
)
return transferId
}
}
}
extension MessengerSendFile {
public static let unimplemented = MessengerSendFile(
run: XCTUnimplemented("\(Self.self)")
)
}
......@@ -12,8 +12,11 @@ public struct MessengerEnvironment {
public var fileManager: MessengerFileManager
public var generateSecret: GenerateSecret
public var getCMixParams: GetCMixParams
public var getE2EFileTransferParams: GetE2EFileTransferParams
public var getE2EParams: GetE2EParams
public var getFileTransferParams: GetFileTransferParams
public var getSingleUseParams: GetSingleUseParams
public var initFileTransfer: InitFileTransfer
public var initializeBackup: InitializeBackup
public var isListeningForMessages: Stored<Bool>
public var isRegisteredWithUD: IsRegisteredWithUD
......@@ -58,8 +61,11 @@ extension MessengerEnvironment {
fileManager: .live(),
generateSecret: .live,
getCMixParams: .liveDefault,
getE2EFileTransferParams: .liveDefault,
getE2EParams: .liveDefault,
getFileTransferParams: .liveDefault,
getSingleUseParams: .liveDefault,
initFileTransfer: .live,
initializeBackup: .live,
isListeningForMessages: .inMemory(false),
isRegisteredWithUD: .live,
......@@ -99,8 +105,11 @@ extension MessengerEnvironment {
fileManager: .unimplemented,
generateSecret: .unimplemented,
getCMixParams: .unimplemented,
getE2EFileTransferParams: .unimplemented,
getE2EParams: .unimplemented,
getFileTransferParams: .unimplemented,
getSingleUseParams: .unimplemented,
initFileTransfer: .unimplemented,
initializeBackup: .unimplemented,
isListeningForMessages: .unimplemented(placeholder: false),
isRegisteredWithUD: .unimplemented,
......
import CustomDump
import XCTest
import XXClient
@testable import XXMessengerClient
final class MessengerSendFileTests: XCTestCase {
func testSendFile() throws {
let e2eId = 123
let e2eFileTransferParams = "e2eFileTransferParams".data(using: .utf8)!
let fileTransferParams = "fileTransferParams".data(using: .utf8)!
let newTransferId = "transferId".data(using: .utf8)!
var didInitFileTransfer: [InitFileTransfer.Params] = []
var didSendFile: [FileTransferSend.Params] = []
var didCloseSend: [Data] = []
var didReceiveCallback: [MessengerSendFile.CallbackInfo] = []
var fileTransferProgressCallback: FileTransferProgressCallback!
var env: MessengerEnvironment = .unimplemented
env.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getId.run = { e2eId }
return e2e
}
env.getE2EFileTransferParams.run = { e2eFileTransferParams }
env.getFileTransferParams.run = { fileTransferParams }
env.initFileTransfer.run = { params, callback in
didInitFileTransfer.append(params)
var fileTransfer: FileTransfer = .unimplemented
fileTransfer.send.run = { params, callback in
didSendFile.append(params)
fileTransferProgressCallback = callback
return newTransferId
}
fileTransfer.closeSend.run = { id in
didCloseSend.append(id)
}
return fileTransfer
}
let sendFile: MessengerSendFile = .live(env)
let params = MessengerSendFile.Params.stub
let transferId = try sendFile(params) { info in
didReceiveCallback.append(info)
}
XCTAssertNoDifference(transferId, newTransferId)
XCTAssertNoDifference(didInitFileTransfer, [
.init(
e2eId: e2eId,
e2eFileTransferParamsJSON: e2eFileTransferParams,
fileTransferParamsJSON: fileTransferParams
)
])
XCTAssertNoDifference(didSendFile, [
.init(
payload: params.file,
recipientId: params.recipientId,
retry: Float(params.retry),
period: params.callbackIntervalMS
)
])
fileTransferProgressCallback.handle(.success(.init(
progress: Progress(
completed: false,
transmitted: 1,
total: 10,
error: nil
),
partTracker: .unimplemented
)))
fileTransferProgressCallback.handle(.success(.init(
progress: Progress(
completed: false,
transmitted: 6,
total: 10,
error: nil
),
partTracker: .unimplemented
)))
fileTransferProgressCallback.handle(.success(.init(
progress: Progress(
completed: true,
transmitted: 10,
total: 10,
error: nil
),
partTracker: .unimplemented
)))
XCTAssertNoDifference(didReceiveCallback, [
.progress(id: transferId, transmitted: 1, total: 10),
.progress(id: transferId, transmitted: 6, total: 10),
.finished(id: transferId),
])
XCTAssertNoDifference(didCloseSend, [transferId])
}
func testSendFileWhenNotConnected() {
var env: MessengerEnvironment = .unimplemented
env.e2e.get = { nil }
let sendFile: MessengerSendFile = .live(env)
XCTAssertThrowsError(try sendFile(.stub) { _ in }) { error in
XCTAssertNoDifference(
error as? MessengerSendFile.Error,
MessengerSendFile.Error.notConnected
)
}
}
func testSendFileCallbackFailure() throws {
var didCloseSend: [Data] = []
var didReceiveCallback: [MessengerSendFile.CallbackInfo] = []
var fileTransferProgressCallback: FileTransferProgressCallback!
var env: MessengerEnvironment = .unimplemented
env.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getId.run = { 123 }
return e2e
}
env.getE2EFileTransferParams.run = { Data() }
env.getFileTransferParams.run = { Data() }
env.initFileTransfer.run = { params, callback in
var fileTransfer: FileTransfer = .unimplemented
fileTransfer.send.run = { _, callback in
fileTransferProgressCallback = callback
return "transferId".data(using: .utf8)!
}
fileTransfer.closeSend.run = { id in
didCloseSend.append(id)
}
return fileTransfer
}
let sendFile: MessengerSendFile = .live(env)
let transferId = try sendFile(.stub) { info in
didReceiveCallback.append(info)
}
let error = NSError(domain: "test", code: 1234)
fileTransferProgressCallback.handle(.failure(error))
XCTAssertNoDifference(didReceiveCallback, [
.failed(id: transferId, .error(error)),
])
XCTAssertNoDifference(didCloseSend, [transferId])
}
func testSendFileProgressError() throws {
var didCloseSend: [Data] = []
var didReceiveCallback: [MessengerSendFile.CallbackInfo] = []
var fileTransferProgressCallback: FileTransferProgressCallback!
var env: MessengerEnvironment = .unimplemented
env.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getId.run = { 123 }
return e2e
}
env.getE2EFileTransferParams.run = { Data() }
env.getFileTransferParams.run = { Data() }
env.initFileTransfer.run = { params, callback in
var fileTransfer: FileTransfer = .unimplemented
fileTransfer.send.run = { _, callback in
fileTransferProgressCallback = callback
return "transferId".data(using: .utf8)!
}
fileTransfer.closeSend.run = { id in
didCloseSend.append(id)
}
return fileTransfer
}
let sendFile: MessengerSendFile = .live(env)
let transferId = try sendFile(.stub) { info in
didReceiveCallback.append(info)
}
let error = "something went wrong"
fileTransferProgressCallback.handle(.success(.init(
progress: .init(
completed: false,
transmitted: 0,
total: 0,
error: error
),
partTracker: .unimplemented
)))
XCTAssertNoDifference(didReceiveCallback, [
.failed(id: transferId, .progressError(error)),
])
XCTAssertNoDifference(didCloseSend, [transferId])
}
func testSendFileCloseError() throws {
let closeError = NSError(domain: "test", code: 1234)
var didReceiveCallback: [MessengerSendFile.CallbackInfo] = []
var fileTransferProgressCallback: FileTransferProgressCallback!
var env: MessengerEnvironment = .unimplemented
env.e2e.get = {
var e2e: E2E = .unimplemented
e2e.getId.run = { 123 }
return e2e
}
env.getE2EFileTransferParams.run = { Data() }
env.getFileTransferParams.run = { Data() }
env.initFileTransfer.run = { params, callback in
var fileTransfer: FileTransfer = .unimplemented
fileTransfer.send.run = { _, callback in
fileTransferProgressCallback = callback
return "transferId".data(using: .utf8)!
}
fileTransfer.closeSend.run = { id in
throw closeError
}
return fileTransfer
}
let sendFile: MessengerSendFile = .live(env)
let transferId = try sendFile(.stub) { info in
didReceiveCallback.append(info)
}
fileTransferProgressCallback.handle(.success(.init(
progress: .init(
completed: true,
transmitted: 1,
total: 1,
error: nil
),
partTracker: .unimplemented
)))
XCTAssertNoDifference(didReceiveCallback, [
.finished(id: transferId),
.failed(id: transferId, .close(closeError)),
])
}
}
private extension MessengerSendFile.Params {
static let stub = MessengerSendFile.Params(
file: FileSend(
name: "file-name",
type: "file-type",
preview: "file-preview".data(using: .utf8)!,
contents: "file-contents".data(using: .utf8)!
),
recipientId: "recipient-id".data(using: .utf8)!,
retry: 123,
callbackIntervalMS: 321
)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment