Quellcode durchsuchen

Partially fixed tests for XCode 8 / Swift 3.

Damian Kołakowski vor 9 Jahren
Ursprung
Commit
7959bc1217

+ 4 - 4
Sources/HttpRouter.swift

@@ -107,11 +107,11 @@ public class HttpRouter {
             params[variableNode.0] = pathToken
             return findHandler(&node.nodes[variableNode.0]!, params: &params, generator: &generator)
         }
-        if let _ = node.nodes[pathToken] {
-            return findHandler(&node.nodes[pathToken]!, params: &params, generator: &generator)
+        if var node = node.nodes[pathToken] {
+            return findHandler(&node, params: &params, generator: &generator)
         }
-        if let _ = node.nodes["*"] {
-            return findHandler(&node.nodes["*"]!, params: &params, generator: &generator)
+        if var node = node.nodes["*"] {
+            return findHandler(&node, params: &params, generator: &generator)
         }
         if let startStarNode = node.nodes["**"] {
             let startStarNodeKeys = startStarNode.nodes.keys

+ 18 - 18
Sources/WebSockets.swift

@@ -26,7 +26,7 @@ public func websocket(
         }
         let protocolSessionClosure: ((Socket) -> Void) = { socket in
             let session = WebSocketSession(socket)
-            var fragmentedOpCode = WebSocketSession.OpCode.Close
+            var fragmentedOpCode = WebSocketSession.OpCode.close
             var payload = [UInt8]() // Used for fragmented frames.
             
             func handleTextPayload(_ frame: WebSocketSession.Frame) throws {
@@ -44,7 +44,7 @@ public func websocket(
                         }
                     } else {
                         payload.append(contentsOf: frame.payload)
-                        fragmentedOpCode = .Text
+                        fragmentedOpCode = .text
                     }
                 }
             }
@@ -58,16 +58,16 @@ public func websocket(
                         handleBinary(session, frame.payload)
                     } else {
                         payload.append(contentsOf: frame.payload)
-                        fragmentedOpCode = .Binary
+                        fragmentedOpCode = .binary
                     }
                 }
             }
             
             func handleOperationCode(_ frame: WebSocketSession.Frame) throws {
                 switch frame.opcode {
-                case .Continue:
+                case .continue:
                     // There is no message to continue, failed immediatelly.
-                    if fragmentedOpCode == .Close {
+                    if fragmentedOpCode == .close {
                         socket.shutdwn()
                     }
                     frame.opcode = fragmentedOpCode
@@ -77,22 +77,22 @@ public func websocket(
                         // Clean the buffer.
                         payload = []
                         // Reset the OpCode.
-                        fragmentedOpCode = WebSocketSession.OpCode.Close
+                        fragmentedOpCode = WebSocketSession.OpCode.close
                     }
                     try handleOperationCode(frame)
-                case .Text:
+                case .text:
                     try handleTextPayload(frame)
-                case .Binary:
+                case .binary:
                     try handleBinaryPayload(frame)
-                case .Close:
+                case .close:
                     throw WebSocketSession.Control.Close
-                case .Ping:
+                case .ping:
                     if frame.payload.count > 125 {
                         throw WebSocketSession.WsError.ProtocolError("Payload gretter than 125 octets.")
                     } else {
-                        session.writeFrame(ArraySlice(frame.payload), .Pong)
+                        session.writeFrame(ArraySlice(frame.payload), .pong)
                     }
-                case .Pong:
+                case .pong:
                     break
                 }
             }
@@ -131,11 +131,11 @@ public func websocket(
 public class WebSocketSession: Hashable, Equatable  {
     
     public enum WsError: Error { case UnknownOpCode(String), UnMaskedFrame(String), ProtocolError(String), InvalidUTF8(String) }
-    public enum OpCode: UInt8 { case Continue = 0x00, Close = 0x08, Ping = 0x09, Pong = 0x0A, Text = 0x01, Binary = 0x02 }
+    public enum OpCode: UInt8 { case `continue` = 0x00, close = 0x08, ping = 0x09, pong = 0x0A, text = 0x01, binary = 0x02 }
     public enum Control: Error { case Close }
     
     public class Frame {
-        public var opcode = OpCode.Close
+        public var opcode = OpCode.close
         public var fin = false
         public var rsv1: UInt8 = 0
         public var rsv2: UInt8 = 0
@@ -155,7 +155,7 @@ public class WebSocketSession: Hashable, Equatable  {
     }
     
     public func writeText(_ text: String) -> Void {
-        self.writeFrame(ArraySlice(text.utf8), OpCode.Text)
+        self.writeFrame(ArraySlice(text.utf8), OpCode.text)
     }
 
     public func writeBinary(_ binary: [UInt8]) -> Void {
@@ -163,7 +163,7 @@ public class WebSocketSession: Hashable, Equatable  {
     }
     
     public func writeBinary(_ binary: ArraySlice<UInt8>) -> Void {
-        self.writeFrame(binary, OpCode.Binary)
+        self.writeFrame(binary, OpCode.binary)
     }
     
     public func writeFrame(_ data: ArraySlice<UInt8>, _ op: OpCode, _ fin: Bool = true) {
@@ -179,7 +179,7 @@ public class WebSocketSession: Hashable, Equatable  {
     }
     
     public func writeCloseFrame() {
-        writeFrame(ArraySlice("".utf8), .Close)
+        writeFrame(ArraySlice("".utf8), .close)
     }
     
     private func encodeLengthAndMaskFlag(_ len: UInt64, _ masked: Bool) -> [UInt8] {
@@ -225,7 +225,7 @@ public class WebSocketSession: Hashable, Equatable  {
         }
         if frm.fin == false {
             switch opcode {
-            case .Ping, .Pong, .Close:
+            case .ping, .pong, .close:
                 // Control frames must not be fragmented
                 // https://tools.ietf.org/html/rfc6455#section-5.5 ( Page 35 )
                 throw WsError.ProtocolError("Control frames must not be framgemted.")

+ 45 - 18
XCode/Swifter.xcodeproj/project.pbxproj

@@ -82,12 +82,31 @@
 		7CCD87611C66099B0068099B /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AE893E71C05127900A29F63 /* Swifter.framework */; };
 		7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */; };
 		7CCD87721C660B250068099B /* SwifterTestsStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */; };
-		7CCD877E1C660EA30068099B /* Swifter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7AE893FB1C0512C400A29F63 /* Swifter.framework */; };
 		7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876D1C660B250068099B /* SwifterTestsHttpParser.swift */; };
 		7CCD87851C660ED60068099B /* SwifterTestsStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */; };
 		7CDAB8131BE2A1D400C8A977 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80D1BE2A1D400C8A977 /* Main.storyboard */; };
 		7CDAB8141BE2A1D400C8A977 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */; };
 		7CDAB8161BE2A1D400C8A977 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CDAB8111BE2A1D400C8A977 /* ViewController.swift */; };
+		7CEBB86E1D94612D00370A6B /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6EB1D2C44F30030FC98 /* File.swift */; };
+		7CEBB86F1D94612D00370A6B /* Files.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6EC1D2C44F30030FC98 /* Files.swift */; };
+		7CEBB8701D94612D00370A6B /* HttpParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6ED1D2C44F30030FC98 /* HttpParser.swift */; };
+		7CEBB8711D94612D00370A6B /* HttpRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6EE1D2C44F30030FC98 /* HttpRequest.swift */; };
+		7CEBB8721D94612D00370A6B /* HttpResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6EF1D2C44F30030FC98 /* HttpResponse.swift */; };
+		7CEBB8731D94612D00370A6B /* HttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F01D2C44F30030FC98 /* HttpRouter.swift */; };
+		7CEBB8741D94612D00370A6B /* HttpServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F11D2C44F30030FC98 /* HttpServer.swift */; };
+		7CEBB8751D94612D00370A6B /* HttpServerIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F21D2C44F30030FC98 /* HttpServerIO.swift */; };
+		7CEBB8761D94612D00370A6B /* Process.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F31D2C44F30030FC98 /* Process.swift */; };
+		7CEBB8771D94612D00370A6B /* Scopes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F41D2C44F30030FC98 /* Scopes.swift */; };
+		7CEBB8781D94612D00370A6B /* Socket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F51D2C44F30030FC98 /* Socket.swift */; };
+		7CEBB8791D94612D00370A6B /* Socket+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B29E1D369BEC00D35BFB /* Socket+File.swift */; };
+		7CEBB87A1D94612D00370A6B /* Socket+Server.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C458EFB1D4A7526006A68E5 /* Socket+Server.swift */; };
+		7CEBB87B1D94612D00370A6B /* String+BASE64.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F61D2C44F30030FC98 /* String+BASE64.swift */; };
+		7CEBB87C1D94612D00370A6B /* String+Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F71D2C44F30030FC98 /* String+Misc.swift */; };
+		7CEBB87D1D94612D00370A6B /* String+SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F81D2C44F30030FC98 /* String+SHA1.swift */; };
+		7CEBB87E1D94612D00370A6B /* WebSockets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B6F91D2C44F30030FC98 /* WebSockets.swift */; };
+		7CEBB87F1D94612D00370A6B /* Errno.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C76B2A11D369C9D00D35BFB /* Errno.swift */; };
+		7CEBB8811D94675A00370A6B /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CEBB8801D94675A00370A6B /* SwifterTestsHttpRouter.swift */; };
+		7CEBB8821D94675A00370A6B /* SwifterTestsHttpRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CEBB8801D94675A00370A6B /* SwifterTestsHttpRouter.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -112,13 +131,6 @@
 			remoteGlobalIDString = 7AE893E61C05127900A29F63;
 			remoteInfo = SwifteriOS;
 		};
-		7CCD877F1C660EA30068099B /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = 7C839B6619422CFF003A6950 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 7AE893FA1C0512C400A29F63;
-			remoteInfo = SwifterMac;
-		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -182,6 +194,7 @@
 		7CDAB80F1BE2A1D400C8A977 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
 		7CDAB8101BE2A1D400C8A977 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		7CDAB8111BE2A1D400C8A977 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
+		7CEBB8801D94675A00370A6B /* SwifterTestsHttpRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwifterTestsHttpRouter.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -232,7 +245,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				7CCD877E1C660EA30068099B /* Swifter.framework in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -356,6 +368,7 @@
 				7CCD876E1C660B250068099B /* SwifterTestsStringExtensions.swift */,
 				7C4785E81C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift */,
 				0858E7F31D68BB2600491CD1 /* IOSafetyTests.swift */,
+				7CEBB8801D94675A00370A6B /* SwifterTestsHttpRouter.swift */,
 			);
 			path = SwifterTestsCommon;
 			sourceTree = "<group>";
@@ -530,7 +543,6 @@
 			buildRules = (
 			);
 			dependencies = (
-				7CCD87801C660EA30068099B /* PBXTargetDependency */,
 			);
 			name = SwifterOSXTests;
 			productName = SwifterOSXTests;
@@ -544,7 +556,7 @@
 			isa = PBXProject;
 			attributes = {
 				LastSwiftUpdateCheck = 0720;
-				LastUpgradeCheck = 0730;
+				LastUpgradeCheck = 0800;
 				ORGANIZATIONNAME = "Damian Kołakowski";
 				TargetAttributes = {
 					7AE893E61C05127900A29F63 = {
@@ -743,6 +755,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				7CCD87701C660B250068099B /* SwifterTestsHttpParser.swift in Sources */,
+				7CEBB8811D94675A00370A6B /* SwifterTestsHttpRouter.swift in Sources */,
 				0858E7F81D68BC2600491CD1 /* PingServer.swift in Sources */,
 				0858E7F41D68BB2600491CD1 /* IOSafetyTests.swift in Sources */,
 				7C4785E91C71D15600A9FE73 /* SwifterTestsWebSocketSession.swift in Sources */,
@@ -754,6 +767,25 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				7CEBB86E1D94612D00370A6B /* File.swift in Sources */,
+				7CEBB86F1D94612D00370A6B /* Files.swift in Sources */,
+				7CEBB8701D94612D00370A6B /* HttpParser.swift in Sources */,
+				7CEBB8711D94612D00370A6B /* HttpRequest.swift in Sources */,
+				7CEBB8721D94612D00370A6B /* HttpResponse.swift in Sources */,
+				7CEBB8731D94612D00370A6B /* HttpRouter.swift in Sources */,
+				7CEBB8741D94612D00370A6B /* HttpServer.swift in Sources */,
+				7CEBB8821D94675A00370A6B /* SwifterTestsHttpRouter.swift in Sources */,
+				7CEBB8751D94612D00370A6B /* HttpServerIO.swift in Sources */,
+				7CEBB8761D94612D00370A6B /* Process.swift in Sources */,
+				7CEBB8771D94612D00370A6B /* Scopes.swift in Sources */,
+				7CEBB8781D94612D00370A6B /* Socket.swift in Sources */,
+				7CEBB8791D94612D00370A6B /* Socket+File.swift in Sources */,
+				7CEBB87A1D94612D00370A6B /* Socket+Server.swift in Sources */,
+				7CEBB87B1D94612D00370A6B /* String+BASE64.swift in Sources */,
+				7CEBB87C1D94612D00370A6B /* String+Misc.swift in Sources */,
+				7CEBB87D1D94612D00370A6B /* String+SHA1.swift in Sources */,
+				7CEBB87E1D94612D00370A6B /* WebSockets.swift in Sources */,
+				7CEBB87F1D94612D00370A6B /* Errno.swift in Sources */,
 				7CCD87841C660ED60068099B /* SwifterTestsHttpParser.swift in Sources */,
 				0858E7F91D68BC2600491CD1 /* PingServer.swift in Sources */,
 				0858E7F51D68BB2600491CD1 /* IOSafetyTests.swift in Sources */,
@@ -780,11 +812,6 @@
 			target = 7AE893E61C05127900A29F63 /* SwifteriOS */;
 			targetProxy = 7CCD87621C66099B0068099B /* PBXContainerItemProxy */;
 		};
-		7CCD87801C660EA30068099B /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 7AE893FA1C0512C400A29F63 /* SwifterMac */;
-			targetProxy = 7CCD877F1C660EA30068099B /* PBXContainerItemProxy */;
-		};
 /* End PBXTargetDependency section */
 
 /* Begin PBXVariantGroup section */
@@ -1160,7 +1187,7 @@
 				MTL_ENABLE_DEBUG_INFO = YES;
 				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterOSXTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = appletvos;
+				SDKROOT = macosx;
 			};
 			name = Debug;
 		};
@@ -1178,7 +1205,7 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				PRODUCT_BUNDLE_IDENTIFIER = pl.kolakowski.SwifterOSXTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
-				SDKROOT = appletvos;
+				SDKROOT = macosx;
 			};
 			name = Release;
 		};

+ 1 - 1
XCode/Swifter.xcodeproj/xcshareddata/xcschemes/SwifterMac.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0730"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"

+ 1 - 1
XCode/Swifter.xcodeproj/xcshareddata/xcschemes/SwifteriOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0730"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"

+ 1 - 1
XCode/Swifter.xcodeproj/xcshareddata/xcschemes/SwiftertvOS.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0730"
+   LastUpgradeVersion = "0800"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"

+ 3 - 4
XCode/SwifterTestsCommon/IOSafetyTests.swift

@@ -7,7 +7,6 @@
 //
 
 import XCTest
-import Swifter
 
 class IOSafetyTests: XCTestCase {
     var server: HttpServer!
@@ -28,10 +27,10 @@ class IOSafetyTests: XCTestCase {
         (0...100).forEach { _ in
             server = HttpServer.pingServer()
             try! server.start()
-            XCTAssertFalse(NSURLSession.sharedSession().retryPing())
+            XCTAssertFalse(URLSession.shared.retryPing())
             (0...100).forEach { _ in
-                dispatch_async(dispatch_get_global_queue(0, 0)) {
-                    NSURLSession.sharedSession().pingTask { _, _, _ in }.resume()
+                DispatchQueue.global(qos: DispatchQoS.default.qosClass).sync {
+                    URLSession.shared.pingTask { _, _, _ in }.resume()
                 }
             }
             server.stop()

+ 15 - 15
XCode/SwifterTestsCommon/PingServer.swift

@@ -23,39 +23,39 @@ extension HttpServer {
 let defaultLocalhost = NSURL(string:"http://localhost:8080")!
 
 // Client
-extension NSURLSession {
+extension URLSession {
     func pingTask(
         hostURL: NSURL = defaultLocalhost,
-        completionHandler handler: (NSData?, NSURLResponse?, NSError?) -> Void
-    ) -> NSURLSessionDataTask {
-        return self.dataTaskWithURL(hostURL.URLByAppendingPathComponent("/ping"), completionHandler: handler)
+        completionHandler handler: @escaping (Data?, URLResponse?, Error?) -> Void
+    ) -> URLSessionDataTask {
+        return self.dataTask(with: hostURL.appendingPathComponent("/ping")!, completionHandler: handler)
     }
     
     func retryPing(
         hostURL: NSURL = defaultLocalhost,
         timeout: Double = 2.0
     ) -> Bool {
-        let semaphore = dispatch_semaphore_create(0)
+        let semaphore = DispatchSemaphore(value: 0)
         self.signalIfPongReceived(semaphore, hostURL: hostURL)
-        let timeoutDate = NSDate().dateByAddingTimeInterval(timeout)
+        let timeoutDate = NSDate().addingTimeInterval(timeout)
         var timedOut = false
-        while dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) != 0 {
-            if NSDate().laterDate(timeoutDate) != timeoutDate {
+        while semaphore.wait(timeout: DispatchTime.now()) != DispatchTimeoutResult.timedOut {
+            if NSDate().laterDate(timeoutDate as Date) != timeoutDate as Date {
                 timedOut = true
                 break
             }
-            NSRunLoop.currentRunLoop().runMode(
-                NSRunLoopCommonModes,
-                beforeDate: NSDate.distantFuture()
+            RunLoop.current.run(
+                mode: RunLoopMode.commonModes,
+                before: NSDate.distantFuture
             )
         }
         return timedOut
     }
     
-    func signalIfPongReceived(semaphore: dispatch_semaphore_t, hostURL: NSURL) {
-        pingTask(hostURL) { data, response, error in
-            if let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 {
-                dispatch_semaphore_signal(semaphore)
+    func signalIfPongReceived(_ semaphore: DispatchSemaphore, hostURL: NSURL) {
+        pingTask(hostURL: hostURL) { data, response, error in
+            if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
+                semaphore.signal()
             } else {
                 self.signalIfPongReceived(semaphore, hostURL: hostURL)
             }

+ 25 - 26
XCode/SwifterTestsCommon/SwifterTestsHttpParser.swift

@@ -6,7 +6,6 @@
 //
 
 import XCTest
-import Swifter
 
 class SwifterTestsHttpParser: XCTestCase {
     
@@ -16,16 +15,16 @@ class SwifterTestsHttpParser: XCTestCase {
         
         init(_ content: String) {
             super.init(socketFileDescriptor: -1)
-            self.content.appendContentsOf([UInt8](content.utf8))
+            self.content.append(contentsOf: [UInt8](content.utf8))
         }
-
+        
         override func read() throws -> UInt8 {
             if offset < content.count {
                 let value = self.content[offset]
                 offset = offset + 1
                 return value
             }
-            throw SocketError.RecvFailed("")
+            throw SocketError.recvFailed("")
         }
     }
     
@@ -33,73 +32,73 @@ class SwifterTestsHttpParser: XCTestCase {
         let parser = HttpParser()
         
         do {
-            try parser.readHttpRequest(TestSocket(""))
+            let _ = try parser.readHttpRequest(TestSocket(""))
             XCTAssert(false, "Parser should throw an error if socket is empty.")
         } catch { }
-
+        
         do {
-            try parser.readHttpRequest(TestSocket("12345678"))
+            let _ = try parser.readHttpRequest(TestSocket("12345678"))
             XCTAssert(false, "Parser should throw an error if status line has single token.")
         } catch { }
-
+        
         do {
-            try parser.readHttpRequest(TestSocket("GET HTTP/1.0"))
+            let _ = try parser.readHttpRequest(TestSocket("GET HTTP/1.0"))
             XCTAssert(false, "Parser should throw an error if status line has not enough tokens.")
         } catch { }
-
+        
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
             XCTAssert(false, "Parser should throw an error if there is no next line symbol.")
         } catch { }
-            
+        
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
             XCTAssert(false, "Parser should throw an error if there is no next line symbol.")
         } catch { }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r"))
             XCTAssert(false, "Parser should throw an error if there is no next line symbol.")
         } catch { }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\n"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\n"))
             XCTAssert(false, "Parser should throw an error if there is no 'Content-Length' header.")
         } catch { }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r\nContent-Length: 0\r\n\r\n"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r\nContent-Length: 0\r\n\r\n"))
         } catch {
             XCTAssert(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
         }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 0\r\n\n"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 0\r\n\n"))
         } catch {
             XCTAssert(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
         }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 5\n\n12345"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 5\n\n12345"))
         } catch {
             XCTAssert(false, "Parser should not throw any errors if there is a valid 'Content-Length' header.")
         }
         
         do {
-            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\r\n\n"))
+            let _ = try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\r\n\n"))
             XCTAssert(false, "Parser should throw an error if request' body is too short.")
         } catch { }
         
         var r = try? parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\n\n1234567890"))
-        XCTAssert(r?.method == "GET", "Parser should extract HTTP method name from the status line.")
-        XCTAssert(r?.path == "/", "Parser should extract HTTP path value from the status line.")
-        XCTAssert(r?.headers["content-length"] == "10", "Parser should extract Content-Length header value.")
+        XCTAssertEqual(r?.method, "GET", "Parser should extract HTTP method name from the status line.")
+        XCTAssertEqual(r?.path, "/", "Parser should extract HTTP path value from the status line.")
+        XCTAssertEqual(r?.headers["content-length"], "10", "Parser should extract Content-Length header value.")
         
         r = try? parser.readHttpRequest(TestSocket("POST / HTTP/1.0\nContent-Length: 10\n\n1234567890"))
-        XCTAssert(r?.method == "POST", "Parser should extract HTTP method name from the status line.")
+        XCTAssertEqual(r?.method, "POST", "Parser should extract HTTP method name from the status line.")
         
         r = try? parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nHeader1: 1\nHeader2: 2\nContent-Length: 0\n\n"))
-        XCTAssert(r?.headers["header1"] == "1", "Parser should extract multiple headers from the request.")
-        XCTAssert(r?.headers["header2"] == "2", "Parser should extract multiple headers from the request.")
+        XCTAssertEqual(r?.headers["header1"], "1", "Parser should extract multiple headers from the request.")
+        XCTAssertEqual(r?.headers["header2"], "2", "Parser should extract multiple headers from the request.")
     }
-}
+}

+ 108 - 0
XCode/SwifterTestsCommon/SwifterTestsHttpRouter.swift

@@ -0,0 +1,108 @@
+//
+//  SwifterTestsHttpRouter.swift
+//  Swifter
+//
+
+//  Copyright © 2016 Damian Kołakowski. All rights reserved.
+//
+
+import XCTest
+
+class SwifterTestsHttpRouter: XCTestCase {
+    
+    func testHttpRouterSlashRoot() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        XCTAssertNotNil(router.route(nil, path: "/"))
+    }
+    
+    func testHttpRouterSimplePathSegments() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/b/c/d", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        XCTAssertNil(router.route(nil, path: "/"))
+        XCTAssertNil(router.route(nil, path: "/a"))
+        XCTAssertNil(router.route(nil, path: "/a/b"))
+        XCTAssertNil(router.route(nil, path: "/a/b/c"))
+        XCTAssertNotNil(router.route(nil, path: "/a/b/c/d"))
+    }
+    
+    func testHttpRouterSinglePathSegmentWildcard() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/*/c/d", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        XCTAssertNil(router.route(nil, path: "/"))
+        XCTAssertNil(router.route(nil, path: "/a"))
+        XCTAssertNotNil(router.route(nil, path: "/a/foo/c/d"))
+        XCTAssertNotNil(router.route(nil, path: "/a/b/c/d"))
+        XCTAssertNil(router.route(nil, path: "/a/b"))
+        XCTAssertNil(router.route(nil, path: "/a/b/foo/d"))
+    }
+    
+    func testHttpRouterVariables() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/:arg1/:arg2/b/c/d/:arg3", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        XCTAssertNil(router.route(nil, path: "/"))
+        XCTAssertNil(router.route(nil, path: "/a"))
+        XCTAssertNil(router.route(nil, path: "/a/b/c/d"))
+        XCTAssertEqual(router.route(nil, path: "/a/value1/value2/b/c/d/value3")?.0[":arg1"], "value1")
+        XCTAssertEqual(router.route(nil, path: "/a/value1/value2/b/c/d/value3")?.0[":arg2"], "value2")
+        XCTAssertEqual(router.route(nil, path: "/a/value1/value2/b/c/d/value3")?.0[":arg3"], "value3")
+    }
+    
+    func testHttpRouterMultiplePathSegmentWildcards() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/**/e/f/g", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        XCTAssertNil(router.route(nil, path: "/"))
+        XCTAssertNil(router.route(nil, path: "/a"))
+        XCTAssertNotNil(router.route(nil, path: "/a/b/c/d/e/f/g"))
+        XCTAssertNil(router.route(nil, path: "/a/e/f/g"))
+    }
+    
+    func testHttpRouterEmptyTail() {
+        
+        let router = HttpRouter()
+        
+        router.register(nil, path: "/a/b/", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        router.register(nil, path: "/a/b/:var", handler: { r in
+            return .OK(.Html("OK"))
+        })
+        
+        
+        XCTAssertNil(router.route(nil, path: "/"))
+        XCTAssertNil(router.route(nil, path: "/a"))
+        XCTAssertNotNil(router.route(nil, path: "/a/b/"))
+        XCTAssertNil(router.route(nil, path: "/a/e/f/g"))
+        
+        XCTAssertEqual(router.route(nil, path: "/a/b/value1")?.0[":var"], "value1")
+        
+        XCTAssertEqual(router.route(nil, path: "/a/b/")?.0[":var"], "")
+    }
+    
+}

+ 10 - 11
XCode/SwifterTestsCommon/SwifterTestsStringExtensions.swift

@@ -6,19 +6,18 @@
 //
 
 import XCTest
-import Swifter
 
 class SwifterTestsStringExtensions: XCTestCase {
     
     func testSHA1() {
-        XCTAssertEqual("".SHA1(), "da39a3ee5e6b4b0d3255bfef95601890afd80709")
-        XCTAssertEqual("test".SHA1(), "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3")
+        XCTAssertEqual("".sha1(), "da39a3ee5e6b4b0d3255bfef95601890afd80709")
+        XCTAssertEqual("test".sha1(), "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3")
         
         // Values copied from OpenSSL:
         // https://github.com/openssl/openssl/blob/master/test/sha1test.c
         
-        XCTAssertEqual("abc".SHA1(), "a9993e364706816aba3e25717850c26c9cd0d89d")
-        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".SHA1(),
+        XCTAssertEqual("abc".sha1(), "a9993e364706816aba3e25717850c26c9cd0d89d")
+        XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".sha1(),
             "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
         
         XCTAssertEqual(
@@ -34,7 +33,7 @@ class SwifterTestsStringExtensions: XCTestCase {
              "a9993e364706816aba3e25717850c26c9cd0d89d" +
              "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
              "a9993e364706816aba3e25717850c26c9cd0d89d" +
-             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").SHA1(),
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").sha1(),
             "a377b0c42d685fdc396e29a9eda7101d900947ca")
     }
     
@@ -82,11 +81,11 @@ class SwifterTestsStringExtensions: XCTestCase {
     }
 
     func testMiscReplace() {
-        XCTAssertEqual("".replace("+", "-"), "")
-        XCTAssertEqual("test".replace("+", "-"), "test")
-        XCTAssertEqual("+++".replace("+", "-"), "---")
-        XCTAssertEqual("t&e&s&t12%3%".replace("&", "+").replace("%", "+"), "t+e+s+t12+3+")
-        XCTAssertEqual("test 1234 #$%^&*( test   ".replace(" ", "_"), "test_1234_#$%^&*(_test___")
+        XCTAssertEqual("".replace(old: "+", "-"), "")
+        XCTAssertEqual("test".replace(old: "+", "-"), "test")
+        XCTAssertEqual("+++".replace(old: "+", "-"), "---")
+        XCTAssertEqual("t&e&s&t12%3%".replace(old: "&", "+").replace(old: "%", "+"), "t+e+s+t12+3+")
+        XCTAssertEqual("test 1234 #$%^&*( test   ".replace(old: " ", "_"), "test_1234_#$%^&*(_test___")
     }
     
     func testMiscRemovePercentEncoding() {

+ 19 - 20
XCode/SwifterTestsCommon/SwifterTestsWebSocketSession.swift

@@ -6,7 +6,6 @@
 //
 
 import XCTest
-import Swifter
 
 class SwifterTestsWebSocketSession: XCTestCase {
     
@@ -16,7 +15,7 @@ class SwifterTestsWebSocketSession: XCTestCase {
         
         init(_ content: [UInt8]) {
             super.init(socketFileDescriptor: -1)
-            self.content.appendContentsOf(content)
+            self.content.append(contentsOf: content)
         }
         
         override func read() throws -> UInt8 {
@@ -25,7 +24,7 @@ class SwifterTestsWebSocketSession: XCTestCase {
                 offset = offset + 1
                 return value
             }
-            throw SocketError.RecvFailed("")
+            throw SocketError.recvFailed("")
         }
     }
     
@@ -33,7 +32,7 @@ class SwifterTestsWebSocketSession: XCTestCase {
         
         do {
             let session = WebSocketSession(TestSocket([0]))
-            try session.readFrame()
+            let _ = try session.readFrame()
             XCTAssert(false, "Parser should throw an error if socket has not enough data for a frame.")
         } catch {
             XCTAssert(true, "Parser should throw an error if socket has not enough data for a frame.")
@@ -41,9 +40,9 @@ class SwifterTestsWebSocketSession: XCTestCase {
         
         do {
             let session = WebSocketSession(TestSocket([0b0000_0001, 0b0000_0000, 0, 0, 0, 0]))
-            try session.readFrame()
+            let _ = try session.readFrame()
             XCTAssert(false, "Parser should not accept unmasked frames.")
-        } catch WebSocketSession.Error.UnMaskedFrame {
+        } catch WebSocketSession.WsError.UnMaskedFrame {
             XCTAssert(true, "Parse should throw UnMaskedFrame error for unmasked message.")
         } catch {
             XCTAssert(false, "Parse should throw UnMaskedFrame error for unmasked message.")
@@ -60,7 +59,7 @@ class SwifterTestsWebSocketSession: XCTestCase {
         do {
             let session = WebSocketSession(TestSocket([0b0000_0000, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Continue, "Parser should accept Continue opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.continue, "Parser should accept Continue opcode.")
         } catch {
             XCTAssertTrue(true, "Parser should accept Continue opcode without any errors.")
         }
@@ -68,7 +67,7 @@ class SwifterTestsWebSocketSession: XCTestCase {
         do {
             let session = WebSocketSession(TestSocket([0b0000_0001, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Text, "Parser should accept Text opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.text, "Parser should accept Text opcode.")
         } catch {
             XCTAssert(false, "Parser should accept Text opcode without any errors.")
         }
@@ -76,41 +75,41 @@ class SwifterTestsWebSocketSession: XCTestCase {
         do {
             let session = WebSocketSession(TestSocket([0b0000_0010, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Binary, "Parser should accept Binary opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.binary, "Parser should accept Binary opcode.")
         } catch {
             XCTAssert(false, "Parser should accept Binary opcode without any errors.")
         }
         
         do {
-            let session = WebSocketSession(TestSocket([0b1000_1000, 0b1000_0000, 0, 0, 0, 0]))
+            let session = WebSocketSession(TestSocket([0b0000_1000, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Close, "Parser should accept Close opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.close, "Parser should accept Close opcode.")
         } catch {
-            XCTAssert(false, "Parser should accept Close opcode without any errors: \(error).")
+            XCTAssert(false, "Parser should accept Close opcode without any errors.")
         }
         
         do {
-            let session = WebSocketSession(TestSocket([0b1000_1001, 0b1000_0000, 0, 0, 0, 0]))
+            let session = WebSocketSession(TestSocket([0b0000_1001, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Ping, "Parser should accept Ping opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.ping, "Parser should accept Ping opcode.")
         } catch {
-            XCTAssert(false, "Parser should accept Ping opcode without any errors: \(error).")
+            XCTAssert(false, "Parser should accept Ping opcode without any errors.")
         }
         
         do {
-            let session = WebSocketSession(TestSocket([0b1000_1010, 0b1000_0000, 0, 0, 0, 0]))
+            let session = WebSocketSession(TestSocket([0b0000_1010, 0b1000_0000, 0, 0, 0, 0]))
             let frame = try session.readFrame()
-            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.Pong, "Parser should accept Pong opcode.")
+            XCTAssertEqual(frame.opcode, WebSocketSession.OpCode.pong, "Parser should accept Pong opcode.")
         } catch {
-            XCTAssert(false, "Parser should accept Pong opcode without any errors: \(error).")
+            XCTAssert(false, "Parser should accept Pong opcode without any errors.")
         }
         
         for opcode in [3, 4, 5, 6, 7, 11, 12, 13, 14, 15] {
             do {
                 let session = WebSocketSession(TestSocket([UInt8(opcode), 0b1000_0000, 0, 0, 0, 0]))
-                try session.readFrame()
+                let _ = try session.readFrame()
                 XCTAssert(false, "Parse should throw an error for unknown opcode: \(opcode)")
-            } catch WebSocketSession.Error.UnknownOpCode(_) {
+            } catch WebSocketSession.WsError.UnknownOpCode(_) {
                 XCTAssert(true, "Parse should throw UnknownOpCode error for unknown opcode.")
             } catch {
                 XCTAssert(false, "Parse should throw UnknownOpCode error for unknown opcode (was \(error)).")