// // Created by Erik Little on 10/21/17. // import Dispatch import Foundation @testable import SocketIO import XCTest class SocketMangerTest : XCTestCase { func testManagerProperties() { XCTAssertNotNil(manager.defaultSocket) XCTAssertNil(manager.engine) XCTAssertFalse(manager.forceNew) XCTAssertEqual(manager.handleQueue, DispatchQueue.main) XCTAssertTrue(manager.reconnects) XCTAssertEqual(manager.reconnectWait, 10) XCTAssertEqual(manager.reconnectWaitMax, 30) XCTAssertEqual(manager.randomizationFactor, 0.5) XCTAssertEqual(manager.status, .notConnected) } func testSettingConfig() { let manager = SocketManager(socketURL: URL(string: "https://example.com/")!) XCTAssertEqual(manager.config.first!, .secure(true)) manager.config = [] XCTAssertEqual(manager.config.first!, .secure(true)) } func testBackoffIntervalCalulation() { XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: -1), Double(manager.reconnectWaitMax)) XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: 0), 15) XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: 1), 22.5) XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: 2), 33.75) XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: 50), Double(manager.reconnectWaitMax)) XCTAssertLessThanOrEqual(manager.reconnectInterval(attempts: 10000), Double(manager.reconnectWaitMax)) XCTAssertGreaterThanOrEqual(manager.reconnectInterval(attempts: -1), Double(manager.reconnectWait)) XCTAssertGreaterThanOrEqual(manager.reconnectInterval(attempts: 0), Double(manager.reconnectWait)) XCTAssertGreaterThanOrEqual(manager.reconnectInterval(attempts: 1), 15) XCTAssertGreaterThanOrEqual(manager.reconnectInterval(attempts: 2), 22.5) XCTAssertGreaterThanOrEqual(manager.reconnectInterval(attempts: 10000), Double(manager.reconnectWait)) } func testManagerCallsConnect() { setUpSockets() socket.expectations[ManagerExpectation.didConnectCalled] = expectation(description: "The manager should call connect on the default socket") socket2.expectations[ManagerExpectation.didConnectCalled] = expectation(description: "The manager should call connect on the socket") socket.connect() socket2.connect() manager.fakeConnecting() manager.fakeConnecting(toNamespace: "/swift") waitForExpectations(timeout: 0.3) } func testManagerDoesNotCallConnectWhenConnectingWithLessThanOneReconnect() { setUpSockets() let expect = expectation(description: "The manager should not call connect on the engine") expect.isInverted = true let engine = TestEngine(client: manager, url: manager.socketURL, options: nil) engine.onConnect = { expect.fulfill() } manager.setTestStatus(.connecting) manager.setCurrentReconnect(currentReconnect: 0) manager.engine = engine manager.connect() waitForExpectations(timeout: 0.3) } func testManagerCallConnectWhenConnectingAndMoreThanOneReconnect() { setUpSockets() let expect = expectation(description: "The manager should call connect on the engine") let engine = TestEngine(client: manager, url: manager.socketURL, options: nil) engine.onConnect = { expect.fulfill() } manager.setTestStatus(.connecting) manager.setCurrentReconnect(currentReconnect: 1) manager.engine = engine manager.connect() waitForExpectations(timeout: 0.8) } func testManagerCallsDisconnect() { setUpSockets() socket.expectations[ManagerExpectation.didDisconnectCalled] = expectation(description: "The manager should call disconnect on the default socket") socket2.expectations[ManagerExpectation.didDisconnectCalled] = expectation(description: "The manager should call disconnect on the socket") socket2.on(clientEvent: .connect) {data, ack in self.manager.disconnect() self.manager.fakeDisconnecting() } socket.connect() socket2.connect() manager.fakeConnecting() manager.fakeConnecting(toNamespace: "/swift") waitForExpectations(timeout: 0.3) } // func testManagerEmitAll() { // setUpSockets() // // socket.expectations[ManagerExpectation.emitAllEventCalled] = expectation(description: "The manager should emit an event to the default socket") // socket2.expectations[ManagerExpectation.emitAllEventCalled] = expectation(description: "The manager should emit an event to the socket") // // socket2.on(clientEvent: .connect) {data, ack in // print("connect") // self.manager.emitAll("event", "testing") // } // // socket.connect() // socket2.connect() // // manager.fakeConnecting(toNamespace: "/swift") // // waitForExpectations(timeout: 0.3) // } func testManagerSetsConfigs() { let queue = DispatchQueue(label: "testQueue") manager = TestManager(socketURL: URL(string: "http://localhost/")!, config: [ .handleQueue(queue), .forceNew(true), .reconnects(false), .reconnectWait(5), .reconnectWaitMax(5), .randomizationFactor(0.7), .reconnectAttempts(5) ]) XCTAssertEqual(manager.handleQueue, queue) XCTAssertTrue(manager.forceNew) XCTAssertFalse(manager.reconnects) XCTAssertEqual(manager.reconnectWait, 5) XCTAssertEqual(manager.reconnectWaitMax, 5) XCTAssertEqual(manager.randomizationFactor, 0.7) XCTAssertEqual(manager.reconnectAttempts, 5) } func testManagerRemovesSocket() { setUpSockets() manager.removeSocket(socket) XCTAssertNil(manager.nsps[socket.nsp]) } private func setUpSockets() { socket = manager.testSocket(forNamespace: "/") socket2 = manager.testSocket(forNamespace: "/swift") } private var manager: TestManager! private var socket: TestSocket! private var socket2: TestSocket! override func setUp() { super.setUp() manager = TestManager(socketURL: URL(string: "http://localhost/")!, config: [.log(false)]) socket = nil socket2 = nil } } public enum ManagerExpectation: String { case didConnectCalled case didDisconnectCalled case emitAllEventCalled } public class TestManager: SocketManager { public func setCurrentReconnect(currentReconnect: Int) { self.currentReconnectAttempt = currentReconnect } public override func disconnect() { setTestStatus(.disconnected) } public func testSocket(forNamespace nsp: String) -> TestSocket { return socket(forNamespace: nsp) as! TestSocket } public func fakeDisconnecting() { engineDidClose(reason: "") } public func fakeConnecting(toNamespace nsp: String = "/") { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { // Fake connecting self.parseEngineMessage("0\(nsp)") } } public override func socket(forNamespace nsp: String) -> SocketIOClient { // set socket to our test socket, the superclass method will get this from nsps nsps[nsp] = TestSocket(manager: self, nsp: nsp) return super.socket(forNamespace: nsp) } } public class TestSocket: SocketIOClient { public var expectations = [ManagerExpectation: XCTestExpectation]() public override func didConnect(toNamespace nsp: String, payload: [String: Any]?) { expectations[ManagerExpectation.didConnectCalled]?.fulfill() expectations[ManagerExpectation.didConnectCalled] = nil super.didConnect(toNamespace: nsp, payload: payload) } public override func didDisconnect(reason: String) { expectations[ManagerExpectation.didDisconnectCalled]?.fulfill() expectations[ManagerExpectation.didDisconnectCalled] = nil super.didDisconnect(reason: reason) } public override func emit(_ event: String, _ items: SocketData..., completion: (() -> ())? = nil) { expectations[ManagerExpectation.emitAllEventCalled]?.fulfill() expectations[ManagerExpectation.emitAllEventCalled] = nil } }