Fix #667 Make no ack an enum case

This commit is contained in:
Erik 2017-05-05 22:35:39 -04:00
parent 58f51d07a2
commit 23c76417d2
No known key found for this signature in database
GPG Key ID: 4930B7C5FBC1A69D
2 changed files with 41 additions and 11 deletions

View File

@ -9,18 +9,43 @@
import XCTest import XCTest
@testable import SocketIO @testable import SocketIO
class SocketAckManagerTest: XCTestCase { class SocketAckManagerTest : XCTestCase {
var ackManager = SocketAckManager() var ackManager = SocketAckManager()
func testAddAcks() { func testAddAcks() {
let callbackExpection = self.expectation(description: "callbackExpection") let callbackExpection = expectation(description: "callbackExpection")
let itemsArray = ["Hi", "ho"] let itemsArray = ["Hi", "ho"]
func callback(_ items: [Any]) { func callback(_ items: [Any]) {
callbackExpection.fulfill() callbackExpection.fulfill()
} }
ackManager.addAck(1, callback: callback) ackManager.addAck(1, callback: callback)
ackManager.executeAck(1, with: itemsArray, onQueue: DispatchQueue.main) ackManager.executeAck(1, with: itemsArray, onQueue: DispatchQueue.main)
waitForExpectations(timeout: 3.0, handler: nil) waitForExpectations(timeout: 3.0, handler: nil)
} }
func testManagerTimeoutAck() {
let callbackExpection = expectation(description: "Manager should timeout ack with noAck status")
let itemsArray = ["Hi", "ho"]
func callback(_ items: [Any]) {
XCTAssertEqual(items.count, 1, "Timed out ack should have one value")
guard let timeoutReason = items[0] as? String else {
XCTFail("Timeout reason should be a string")
return
}
XCTAssertEqual(timeoutReason, SocketAckStatus.noAck.rawValue)
callbackExpection.fulfill()
}
ackManager.addAck(1, callback: callback)
ackManager.timeoutAck(1, onQueue: DispatchQueue.main)
waitForExpectations(timeout: 0.2, handler: nil)
}
} }

View File

@ -22,19 +22,24 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
import Dispatch
import Foundation import Foundation
public enum SocketAckStatus : String {
case noAck = "NO ACK"
}
private struct SocketAck : Hashable { private struct SocketAck : Hashable {
let ack: Int let ack: Int
var callback: AckCallback! var callback: AckCallback!
var hashValue: Int { var hashValue: Int {
return ack.hashValue return ack.hashValue
} }
init(ack: Int) { init(ack: Int) {
self.ack = ack self.ack = ack
} }
init(ack: Int, callback: @escaping AckCallback) { init(ack: Int, callback: @escaping AckCallback) {
self.ack = ack self.ack = ack
self.callback = callback self.callback = callback
@ -52,28 +57,28 @@ private func ==(lhs: SocketAck, rhs: SocketAck) -> Bool {
struct SocketAckManager { struct SocketAckManager {
private var acks = Set<SocketAck>(minimumCapacity: 1) private var acks = Set<SocketAck>(minimumCapacity: 1)
private let ackSemaphore = DispatchSemaphore(value: 1) private let ackSemaphore = DispatchSemaphore(value: 1)
mutating func addAck(_ ack: Int, callback: @escaping AckCallback) { mutating func addAck(_ ack: Int, callback: @escaping AckCallback) {
acks.insert(SocketAck(ack: ack, callback: callback)) acks.insert(SocketAck(ack: ack, callback: callback))
} }
/// Should be called on handle queue /// Should be called on handle queue
mutating func executeAck(_ ack: Int, with items: [Any], onQueue: DispatchQueue) { mutating func executeAck(_ ack: Int, with items: [Any], onQueue: DispatchQueue) {
ackSemaphore.wait() ackSemaphore.wait()
defer { ackSemaphore.signal() } defer { ackSemaphore.signal() }
let ack = acks.remove(SocketAck(ack: ack)) let ack = acks.remove(SocketAck(ack: ack))
onQueue.async() { ack?.callback(items) } onQueue.async() { ack?.callback(items) }
} }
/// Should be called on handle queue /// Should be called on handle queue
mutating func timeoutAck(_ ack: Int, onQueue: DispatchQueue) { mutating func timeoutAck(_ ack: Int, onQueue: DispatchQueue) {
ackSemaphore.wait() ackSemaphore.wait()
defer { ackSemaphore.signal() } defer { ackSemaphore.signal() }
let ack = acks.remove(SocketAck(ack: ack)) let ack = acks.remove(SocketAck(ack: ack))
onQueue.async() { onQueue.async() {
ack?.callback?(["NO ACK"]) ack?.callback?([SocketAckStatus.noAck.rawValue])
} }
} }
} }