Use errors in parsing method

This commit is contained in:
Erik Little 2017-08-18 11:04:06 -04:00
parent 079c8e4e4c
commit afbf2cfc40
No known key found for this signature in database
GPG Key ID: 4930B7C5FBC1A69D
3 changed files with 96 additions and 98 deletions

View File

@ -12,7 +12,7 @@ import XCTest
class SocketBasicPacketTest: XCTestCase {
let data = "test".data(using: String.Encoding.utf8)!
let data2 = "test2".data(using: String.Encoding.utf8)!
func testEmpyEmit() {
let expectedSendString = "2[\"test\"]"
let sendData = ["test"]
@ -20,75 +20,75 @@ class SocketBasicPacketTest: XCTestCase {
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testNullEmit() {
let expectedSendString = "2[\"test\",null]"
let sendData: [Any] = ["test", NSNull()]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testStringEmit() {
let expectedSendString = "2[\"test\",\"foo bar\"]"
let sendData = ["test", "foo bar"]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testStringEmitWithQuotes() {
let expectedSendString = "2[\"test\",\"\\\"he\\\"llo world\\\"\"]"
let sendData = ["test", "\"he\"llo world\""]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testJSONEmit() {
let expectedSendString = "2[\"test\",{\"null\":null,\"hello\":1,\"test\":\"hello\",\"foobar\":true}]"
let sendData: [Any] = ["test", ["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testArrayEmit() {
let expectedSendString = "2[\"test\",[\"hello\",1,{\"test\":\"test\"}]]"
let sendData: [Any] = ["test", ["hello", 1, ["test": "test"]]]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testBinaryEmit() {
let expectedSendString = "51-[\"test\",{\"_placeholder\":true,\"num\":0}]"
let sendData: [Any] = ["test", data]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data])
}
func testMultipleBinaryEmit() {
let expectedSendString = "52-[\"test\",{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
let sendData: [Any] = ["test", ["data1": data, "data2": data2] as NSDictionary]
let packet = SocketPacket.packetFromEmit(sendData, id: -1, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data2, data])
}
func testEmitWithAck() {
let expectedSendString = "20[\"test\"]"
let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: false)
XCTAssertEqual(packet.packetString,
expectedSendString)
}
func testEmitDataWithAck() {
let expectedSendString = "51-0[\"test\",{\"_placeholder\":true,\"num\":0}]"
let sendData: [Any] = ["test", data]
@ -97,70 +97,67 @@ class SocketBasicPacketTest: XCTestCase {
XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data])
}
// Acks
func testEmptyAck() {
let expectedSendString = "30[]"
let packet = SocketPacket.packetFromEmit([], id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testNullAck() {
let expectedSendString = "30[null]"
let sendData = [NSNull()]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testStringAck() {
let expectedSendString = "30[\"test\"]"
let sendData = ["test"]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testJSONAck() {
let expectedSendString = "30[{\"null\":null,\"hello\":1,\"test\":\"hello\",\"foobar\":true}]"
let sendData = [["foobar": true, "hello": 1, "test": "hello", "null": NSNull()]]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
}
func testBinaryAck() {
let expectedSendString = "61-0[{\"_placeholder\":true,\"num\":0}]"
let sendData = [data]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data])
}
func testMultipleBinaryAck() {
let expectedSendString = "62-0[{\"data2\":{\"_placeholder\":true,\"num\":0},\"data1\":{\"_placeholder\":true,\"num\":1}}]"
let sendData = [["data1": data, "data2": data2]]
let packet = SocketPacket.packetFromEmit(sendData, id: 0, nsp: "/", ack: true)
XCTAssertEqual(packet.packetString, expectedSendString)
XCTAssertEqual(packet.binary, [data2, data])
}
func testBinaryStringPlaceholderInMessage() {
let engineString = "52-[\"test\",\"~~0\",{\"num\":0,\"_placeholder\":true},{\"_placeholder\":true,\"num\":1}]"
let socket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
socket.setTestable()
if case let .right(packet) = socket.parseString(engineString) {
var packet = packet
XCTAssertEqual(packet.event, "test")
_ = packet.addData(data)
_ = packet.addData(data2)
XCTAssertEqual(packet.args[0] as? String, "~~0")
} else {
XCTFail()
}
var packet = try! socket.parseString(engineString)
XCTAssertEqual(packet.event, "test")
_ = packet.addData(data)
_ = packet.addData(data2)
XCTAssertEqual(packet.args[0] as? String, "~~0")
}
}

View File

@ -11,7 +11,7 @@ import XCTest
class SocketParserTest: XCTestCase {
let testSocket = SocketIOClient(socketURL: URL(string: "http://localhost/")!)
//Format key: message; namespace-data-binary-id
static let packetTypes: [String: (String, [Any], [Data], Int)] = [
"0": ("/", [], [], -1), "1": ("/", [], [], -1),
@ -29,7 +29,7 @@ class SocketParserTest: XCTestCase {
"4{\"test\":2}": ("/", [["test": 2]], [], -1),
"41": ("/", [1], [], -1),
"4[1, \"hello\"]": ("/", [1, "hello"], [], -1)]
func testDisconnect() {
let message = "1"
validateParseResult(message)
@ -39,82 +39,82 @@ class SocketParserTest: XCTestCase {
let message = "0"
validateParseResult(message)
}
func testDisconnectNameSpace() {
let message = "1/swift"
validateParseResult(message)
}
func testConnecttNameSpace() {
let message = "0/swift"
validateParseResult(message)
}
func testIdEvent() {
let message = "25[\"test\"]"
validateParseResult(message)
}
func testBinaryPlaceholderAsString() {
let message = "2[\"test\",\"~~0\"]"
validateParseResult(message)
}
func testNameSpaceArrayParse() {
let message = "2/swift,[\"testArrayEmitReturn\",[\"test3\",\"test4\"]]"
validateParseResult(message)
}
func testNameSpaceArrayAckParse() {
let message = "3/swift,0[[\"test3\",\"test4\"]]"
validateParseResult(message)
}
func testNameSpaceBinaryEventParse() {
let message = "51-/swift,[\"testMultipleItemsWithBufferEmitReturn\",[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
validateParseResult(message)
}
func testNameSpaceBinaryAckParse() {
let message = "61-/swift,19[[1,2],{\"test\":\"bob\"},25,\"polo\",{\"_placeholder\":true,\"num\":0}]"
validateParseResult(message)
}
func testNamespaceErrorParse() {
let message = "4/swift,"
validateParseResult(message)
}
func testErrorTypeString() {
let message = "4\"ERROR\""
validateParseResult(message)
}
func testErrorTypeDictionary() {
let message = "4{\"test\":2}"
validateParseResult(message)
}
func testErrorTypeInt() {
let message = "41"
validateParseResult(message)
}
func testErrorTypeArray() {
let message = "4[1, \"hello\"]"
validateParseResult(message)
}
func testInvalidInput() {
let message = "8"
switch testSocket.parseString(message) {
case .left(_):
return
case .right(_):
XCTFail("Created packet when shouldn't have")
do {
let _ = try testSocket.parseString(message)
XCTFail()
} catch {
}
}
func testGenericParser() {
var parser = SocketStringReader(message: "61-/swift,")
XCTAssertEqual(parser.read(count: 1), "6")
@ -122,27 +122,24 @@ class SocketParserTest: XCTestCase {
XCTAssertEqual(parser.readUntilOccurence(of: "-"), "1")
XCTAssertEqual(parser.currentCharacter, "/")
}
func validateParseResult(_ message: String) {
let validValues = SocketParserTest.packetTypes[message]!
let packet = testSocket.parseString(message)
let packet = try! testSocket.parseString(message)
let type = String(message.characters.prefix(1))
if case let .right(packet) = packet {
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
XCTAssertEqual(packet.nsp, validValues.0)
XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1), "\(packet.data)")
XCTAssertTrue((packet.binary as NSArray).isEqual(to: validValues.2), "\(packet.binary)")
XCTAssertEqual(packet.id, validValues.3)
} else {
XCTFail()
}
XCTAssertEqual(packet.type, SocketPacket.PacketType(rawValue: Int(type) ?? -1)!)
XCTAssertEqual(packet.nsp, validValues.0)
XCTAssertTrue((packet.data as NSArray).isEqual(to: validValues.1), "\(packet.data)")
XCTAssertTrue((packet.binary as NSArray).isEqual(to: validValues.2), "\(packet.binary)")
XCTAssertEqual(packet.id, validValues.3)
}
func testParsePerformance() {
let keys = Array(SocketParserTest.packetTypes.keys)
measure {
for item in keys.enumerated() {
_ = self.testSocket.parseString(item.element)
_ = try! self.testSocket.parseString(item.element)
}
}
}

View File

@ -27,6 +27,12 @@ protocol SocketParsable {
func parseSocketMessage(_ message: String)
}
enum SocketParsableError : Error {
case invalidDataArray
case invalidPacket
case invalidPacketType
}
extension SocketParsable where Self: SocketIOClientSpec {
private func isCorrectNamespace(_ nsp: String) -> Bool {
return nsp == self.nsp
@ -62,15 +68,15 @@ extension SocketParsable where Self: SocketIOClientSpec {
}
/// Parses a messsage from the engine. Returning either a string error or a complete SocketPacket
func parseString(_ message: String) -> Either<String, SocketPacket> {
func parseString(_ message: String) throws -> SocketPacket {
var reader = SocketStringReader(message: message)
guard let type = Int(reader.read(count: 1)).flatMap({ SocketPacket.PacketType(rawValue: $0) }) else {
return .left("Invalid packet type")
throw SocketParsableError.invalidPacketType
}
if !reader.hasNext {
return .right(SocketPacket(type: type, nsp: "/"))
return SocketPacket(type: type, nsp: "/")
}
var namespace = "/"
@ -80,7 +86,7 @@ extension SocketParsable where Self: SocketIOClientSpec {
if let holders = Int(reader.readUntilOccurence(of: "-")) {
placeholders = holders
} else {
return .left("Invalid packet")
throw SocketParsableError.invalidPacket
}
}
@ -89,7 +95,7 @@ extension SocketParsable where Self: SocketIOClientSpec {
}
if !reader.hasNext {
return .right(SocketPacket(type: type, nsp: namespace, placeholders: placeholders))
return SocketPacket(type: type, nsp: namespace, placeholders: placeholders)
}
var idString = ""
@ -113,21 +119,17 @@ extension SocketParsable where Self: SocketIOClientSpec {
dataArray = "[" + dataArray + "]"
}
switch parseData(dataArray) {
case let .left(err):
return .left(err)
case let .right(data):
return .right(SocketPacket(type: type, data: data, id: Int(idString) ?? -1,
nsp: namespace, placeholders: placeholders))
}
let data = try parseData(dataArray)
return SocketPacket(type: type, data: data, id: Int(idString) ?? -1, nsp: namespace, placeholders: placeholders)
}
// Parses data for events
private func parseData(_ data: String) -> Either<String, [Any]> {
private func parseData(_ data: String) throws -> [Any] {
do {
return .right(try data.toArray())
return try data.toArray()
} catch {
return .left("Error parsing data for packet")
throw SocketParsableError.invalidDataArray
}
}
@ -137,12 +139,14 @@ extension SocketParsable where Self: SocketIOClientSpec {
DefaultSocketLogger.Logger.log("Parsing %@", type: "SocketParser", args: message)
switch parseString(message) {
case let .left(err):
DefaultSocketLogger.Logger.error("\(err): %@", type: "SocketParser", args: message)
case let .right(pack):
DefaultSocketLogger.Logger.log("Decoded packet as: %@", type: "SocketParser", args: pack.description)
handlePacket(pack)
do {
let packet = try parseString(message)
DefaultSocketLogger.Logger.log("Decoded packet as: %@", type: "SocketParser", args: packet.description)
handlePacket(packet)
} catch {
DefaultSocketLogger.Logger.error("\(error): %@", type: "SocketParser", args: message)
}
}