Jelajahi Sumber

Added tests for HttpParser ( status line and headers parsing procedure ).
Added tests for SHA1 ( very long content ).

Damian Kołakowski 10 tahun lalu
induk
melakukan
e687721bc6

+ 5 - 3
Sources/HttpParser.swift

@@ -15,9 +15,11 @@ enum HttpParserError: ErrorType {
     case InvalidStatusLine(String)
 }
 
-class HttpParser {
+public class HttpParser {
     
-    func readHttpRequest(socket: Socket) throws -> HttpRequest {
+    public init() { }
+    
+    public func readHttpRequest(socket: Socket) throws -> HttpRequest {
         let statusLine = try socket.readLine()
         let statusLineTokens = statusLine.split(" ")
         if statusLineTokens.count < 3 {
@@ -49,7 +51,7 @@ class HttpParser {
     
     private func readBody(socket: Socket, size: Int) throws -> [UInt8] {
         var body = [UInt8]()
-        for _ in 1...size { body.append(try socket.read()) }
+        for _ in 0..<size { body.append(try socket.read()) }
         return body
     }
     

+ 2 - 2
Sources/Socket.swift

@@ -13,7 +13,7 @@
 
 /* Low level routines for POSIX sockets */
 
-enum SocketError: ErrorType {
+public enum SocketError: ErrorType {
     case SocketCreationFailed(String)
     case SocketSettingReUseAddrFailed(String)
     case BindFailed(String)
@@ -82,7 +82,7 @@ public class Socket: Hashable, Equatable {
     
     private let socketFileDescriptor: Int32
     
-    init(socketFileDescriptor: Int32) {
+    public init(socketFileDescriptor: Int32) {
         self.socketFileDescriptor = socketFileDescriptor
     }
     

+ 91 - 1
SwifterTests/SwifterTestsHttpParser.swift

@@ -11,6 +11,96 @@ import Swifter
 
 class SwifterTestsHttpParser: XCTestCase {
     
+    class TestSocket: Socket {
+        var content = [UInt8]()
+        var offset = 0
+        
+        init(_ content: String) {
+            super.init(socketFileDescriptor: -1)
+            self.content.appendContentsOf([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("")
+        }
+    }
     
-    
+    func testParser() {
+        let parser = HttpParser()
+        
+        do {
+            try parser.readHttpRequest(TestSocket(""))
+            XCTAssertTrue(false, "Parser should throw an error if socket is empty.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("12345678"))
+            XCTAssertTrue(false, "Parser should throw an error if status line has single token.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("GET HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if status line has not enough tokens.")
+        } catch { }
+
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+            
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\r"))
+            XCTAssertTrue(false, "Parser should throw an error if there is no next line symbol.")
+        } catch { }
+        
+        do {
+            try parser.readHttpRequest(TestSocket("GET / HTTP/1.0\n"))
+            XCTAssertTrue(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"))
+        } catch {
+            XCTAssertTrue(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"))
+        } catch {
+            XCTAssertTrue(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"))
+        } catch {
+            XCTAssertTrue(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"))
+            XCTAssertTrue(false, "Parser should  throw an error could not reat the number of bytes defined by 'Content-Length' header.")
+        } catch { }
+        
+        var r = try? parser.readHttpRequest(TestSocket("GET / HTTP/1.0\nContent-Length: 10\n\n1234567890"))
+        XCTAssertTrue(r?.method == "GET", "Parser should extract HTTP method name from the status line.")
+        XCTAssertTrue(r?.path == "/", "Parser should extract HTTP path value from the status line.")
+        XCTAssertTrue(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"))
+        XCTAssertTrue(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"))
+        XCTAssertTrue(r?.headers["header1"] == "1", "Parser should extract multiple headers from the request.")
+        XCTAssertTrue(r?.headers["header2"] == "2", "Parser should extract multiple headers from the request.")
+    }
 }

+ 16 - 0
SwifterTests/SwifterTestsStringExtensions.swift

@@ -21,6 +21,22 @@ class SwifterTestsStringExtensions: XCTestCase {
         XCTAssertEqual("abc".SHA1(), "a9993e364706816aba3e25717850c26c9cd0d89d")
         XCTAssertEqual("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq".SHA1(),
             "84983e441c3bd26ebaae4aa1f95129e5e54670f1")
+        
+        XCTAssertEqual(
+            ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +
+             "a9993e364706816aba3e25717850c26c9cd0d89d" +
+             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq").SHA1(),
+            "a377b0c42d685fdc396e29a9eda7101d900947ca")
     }
     
     func testBASE64() {