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

Refactor MessengerSendFile and add tests

parent 73a6adff
No related branches found
No related tags found
2 merge requests!122Messenger send file,!102Release 1.0.0
...@@ -3,18 +3,49 @@ import XCTestDynamicOverlay ...@@ -3,18 +3,49 @@ import XCTestDynamicOverlay
import XXClient import XXClient
public struct MessengerSendFile { public struct MessengerSendFile {
public typealias Callback = (Data, XXClient.Progress) -> Void 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 { public enum Error: Swift.Error, Equatable {
case notConnected case notConnected
} }
public var run: (FileTransferSend.Params, @escaping Callback) throws -> Void public var run: (Params, @escaping Callback) throws -> Data
public func callAsFunction( public func callAsFunction(
_ params: FileTransferSend.Params, _ params: Params,
callback: @escaping Callback callback: @escaping Callback
) throws -> Void { ) throws -> Data {
try run(params, callback) try run(params, callback)
} }
} }
...@@ -35,33 +66,48 @@ extension MessengerSendFile { ...@@ -35,33 +66,48 @@ extension MessengerSendFile {
fatalError("Bindings issue: ReceiveFileCallback called when sending file.") fatalError("Bindings issue: ReceiveFileCallback called when sending file.")
} }
) )
let semaphore = DispatchSemaphore(value: 0) func close(id: Data) {
do {
try fileTransfer.closeSend(transferId: id)
} catch {
callback(.failed(id: id, .close(error as NSError)))
}
}
var transferId: Data! var transferId: Data!
var error: Swift.Error?
transferId = try fileTransfer.send( transferId = try fileTransfer.send(
params: params, params: FileTransferSend.Params(
payload: params.file,
recipientId: params.recipientId,
retry: Float(params.retry),
period: params.callbackIntervalMS
),
callback: FileTransferProgressCallback { result in callback: FileTransferProgressCallback { result in
guard let transferId else { guard let transferId else {
fatalError("Bindings issue: file transfer progress callback was called before send function returned transfer id.") fatalError("Bindings issue: file transfer progress callback was called before send function returned transfer id.")
} }
switch result { switch result {
case .failure(let err): case .failure(let error):
error = err callback(.failed(id: transferId, .error(error)))
semaphore.signal() close(id: transferId)
case .success(let cb): case .success(let cb):
callback(transferId, cb.progress) if let error = cb.progress.error {
if cb.progress.completed || cb.progress.error != nil { callback(.failed(id: transferId, .progressError(error)))
semaphore.signal() 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
))
} }
} }
} }
) )
semaphore.wait() return transferId
try fileTransfer.closeSend(transferId: transferId)
if let error {
throw error
}
} }
} }
} }
......
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.
Finish editing this message first!
Please register or to comment