361 lines
18 KiB
Swift
361 lines
18 KiB
Swift
import XCTest
|
|
|
|
@testable import SwiftServerHttp
|
|
|
|
class SwiftServerHttpTests: XCTestCase {
|
|
func testResponseOK() {
|
|
let request = HTTPRequest(method: .GET, target:"/echo", httpVersion: (1, 1), headers: HTTPHeaders([("X-foo", "bar")]))
|
|
let resolver = TestResponseResolver(request: request, requestBody: Data())
|
|
resolver.resolveHandler(EchoWebApp().serve)
|
|
XCTAssertNotNil(resolver.response)
|
|
XCTAssertNotNil(resolver.responseBody)
|
|
XCTAssertEqual(HTTPResponseStatus.ok.code, resolver.response?.status.code ?? 0)
|
|
}
|
|
|
|
func testEcho() {
|
|
let testString="This is a test"
|
|
let request = HTTPRequest(method: .POST, target:"/echo", httpVersion: (1, 1), headers: HTTPHeaders([("X-foo", "bar")]))
|
|
let resolver = TestResponseResolver(request: request, requestBody: testString.data(using: .utf8)!)
|
|
resolver.resolveHandler(EchoWebApp().serve)
|
|
XCTAssertNotNil(resolver.response)
|
|
XCTAssertNotNil(resolver.responseBody)
|
|
XCTAssertEqual(HTTPResponseStatus.ok.code, resolver.response?.status.code ?? 0)
|
|
XCTAssertEqual(testString, String(data: resolver.responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
}
|
|
|
|
func testHello() {
|
|
let request = HTTPRequest(method: .GET, target:"/helloworld", httpVersion: (1, 1), headers: HTTPHeaders([("X-foo", "bar")]))
|
|
let resolver = TestResponseResolver(request: request, requestBody: Data())
|
|
resolver.resolveHandler(HelloWorldWebApp().serve)
|
|
XCTAssertNotNil(resolver.response)
|
|
XCTAssertNotNil(resolver.responseBody)
|
|
XCTAssertEqual(HTTPResponseStatus.ok.code, resolver.response?.status.code ?? 0)
|
|
XCTAssertEqual("Hello, World!", String(data: resolver.responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
}
|
|
|
|
func testHeaders() {
|
|
var headers = HTTPHeaders()
|
|
let initialCount = headers.makeIterator().reduce(0) { (last, element) -> Int in return last + 1 }
|
|
XCTAssertEqual(0, initialCount)
|
|
|
|
headers.append(newHeader: ("Test-Header","Test Value"))
|
|
let nextCount = headers.makeIterator().reduce(0) { (last, element) -> Int in return last + 1 }
|
|
XCTAssertEqual(1, nextCount)
|
|
|
|
let testHeaderValueArray = headers["test-header"]
|
|
XCTAssertNotNil(testHeaderValueArray)
|
|
XCTAssertEqual(1,testHeaderValueArray.count)
|
|
XCTAssertEqual("Test Value",testHeaderValueArray.first ?? "Not Found")
|
|
|
|
headers.append(newHeader: ("Test-header","Test Value 2"))
|
|
let testHeaderValueArray2 = headers["test-header"]
|
|
XCTAssertNotNil(testHeaderValueArray2)
|
|
XCTAssertEqual(2,testHeaderValueArray2.count)
|
|
XCTAssertEqual("Test Value",testHeaderValueArray2.first ?? "Not Found")
|
|
let testHeaderValueArray2Remainder = testHeaderValueArray2.dropFirst()
|
|
XCTAssertEqual("Test Value 2",testHeaderValueArray2Remainder.first ?? "Not Found")
|
|
|
|
//This should overwrites, since the subscript is documented to use lowercase keys
|
|
headers["TEST-HEADER"]=["Test Value 3"]
|
|
let testHeaderValueArray3 = headers["test-header"]
|
|
XCTAssertNotNil(testHeaderValueArray3)
|
|
XCTAssertEqual(1,testHeaderValueArray3.count)
|
|
|
|
//Overwrite
|
|
headers["TEST-HEADER"]=["Test Value 4a","Test Value 4b"]
|
|
let testHeaderValueArray4 = headers["test-header"]
|
|
XCTAssertNotNil(testHeaderValueArray4)
|
|
XCTAssertEqual(2,testHeaderValueArray4.count)
|
|
XCTAssertEqual("Test Value 4a",testHeaderValueArray4.first ?? "Not Found")
|
|
let testHeaderValueArray4Remainder = testHeaderValueArray4.dropFirst()
|
|
XCTAssertEqual("Test Value 4b",testHeaderValueArray4Remainder.first ?? "Not Found")
|
|
|
|
}
|
|
|
|
func testResponseCodes() {
|
|
let okay = HTTPResponseStatus.ok
|
|
XCTAssertEqual(200,okay.code)
|
|
XCTAssertEqual("ok",okay.reasonPhrase)
|
|
XCTAssertEqual("CONTINUE",HTTPResponseStatus.continue.reasonPhrase)
|
|
XCTAssertEqual(HTTPResponseStatus.notFound, HTTPResponseStatus.from(code: 404))
|
|
}
|
|
|
|
func testSimpleHello() {
|
|
let request = HTTPRequest(method: .GET, target:"/helloworld", httpVersion: (1, 1), headers: HTTPHeaders([("X-foo", "bar")]))
|
|
let resolver = TestResponseResolver(request: request, requestBody: Data())
|
|
let simpleHelloWebApp = SimpleResponseCreator { (request, body) -> (reponse: HTTPResponse, responseBody: Data) in
|
|
return (HTTPResponse(httpVersion: request.httpVersion,
|
|
status: .ok,
|
|
transferEncoding: .chunked,
|
|
headers: HTTPHeaders([("X-foo", "bar")])),
|
|
"Hello, World!".data(using: .utf8)!)
|
|
|
|
}
|
|
resolver.resolveHandler(simpleHelloWebApp.serve)
|
|
XCTAssertNotNil(resolver.response)
|
|
XCTAssertNotNil(resolver.responseBody)
|
|
XCTAssertEqual(HTTPResponseStatus.ok.code, resolver.response?.status.code ?? 0)
|
|
XCTAssertEqual("Hello, World!", String(data: resolver.responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
}
|
|
|
|
func testHelloEndToEnd() {
|
|
let receivedExpectation = self.expectation(description: "Received web response \(#function)")
|
|
|
|
let server = BlueSocketSimpleServer()
|
|
do {
|
|
try server.start(port: 0, webapp: HelloWorldWebApp().serve)
|
|
let session = URLSession(configuration: URLSessionConfiguration.default)
|
|
let url = URL(string: "http://localhost:\(server.port)/helloworld")!
|
|
print("Test \(#function) on port \(server.port)")
|
|
let dataTask = session.dataTask(with: url) { (responseBody, rawResponse, error) in
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
XCTAssertNotNil(responseBody)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
XCTAssertEqual("Hello, World!", String(data: responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
receivedExpectation.fulfill()
|
|
}
|
|
dataTask.resume()
|
|
self.waitForExpectations(timeout: 10) { (error) in
|
|
if let error = error {
|
|
XCTFail("\(error)")
|
|
}
|
|
}
|
|
server.stop()
|
|
} catch {
|
|
XCTFail("Error listening on port \(0): \(error). Use server.failed(callback:) to handle")
|
|
}
|
|
}
|
|
|
|
func testSimpleHelloEndToEnd() {
|
|
let receivedExpectation = self.expectation(description: "Received web response \(#function)")
|
|
let simpleHelloWebApp = SimpleResponseCreator { (request, body) -> (reponse: HTTPResponse, responseBody: Data) in
|
|
return (HTTPResponse(httpVersion: request.httpVersion,
|
|
status: .ok,
|
|
transferEncoding: .chunked,
|
|
headers: HTTPHeaders([("X-foo", "bar")])),
|
|
"Hello, World!".data(using: .utf8)!)
|
|
|
|
}
|
|
|
|
let server = BlueSocketSimpleServer()
|
|
do {
|
|
try server.start(port: 0, webapp: simpleHelloWebApp.serve)
|
|
} catch {
|
|
XCTFail("Error listening on port \(0): \(error). Use server.failed(callback:) to handle")
|
|
}
|
|
|
|
let session = URLSession(configuration: URLSessionConfiguration.default)
|
|
let url = URL(string: "http://localhost:\(server.port)/helloworld")!
|
|
print("Test \(#function) on port \(server.port)")
|
|
let dataTask = session.dataTask(with: url) { (responseBody, rawResponse, error) in
|
|
print("\(#function) dataTask returned")
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
XCTAssertNotNil(responseBody)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
let responseString = String(data: responseBody ?? Data(), encoding: .utf8) ?? "Nil"
|
|
XCTAssertEqual("Hello, World!", responseString)
|
|
print("\(#function) fulfilling expectation")
|
|
receivedExpectation.fulfill()
|
|
}
|
|
dataTask.resume()
|
|
self.waitForExpectations(timeout: 10) { (error) in
|
|
if let error = error {
|
|
XCTFail("\(error)")
|
|
}
|
|
}
|
|
server.stop()
|
|
print("\(#function) stopping server")
|
|
}
|
|
|
|
|
|
func testRequestEchoEndToEnd() {
|
|
let receivedExpectation = self.expectation(description: "Received web response \(#function)")
|
|
let testString="This is a test"
|
|
|
|
let server = BlueSocketSimpleServer()
|
|
do {
|
|
try server.start(port: 0, webapp: EchoWebApp().serve)
|
|
let session = URLSession(configuration: URLSessionConfiguration.default)
|
|
let url = URL(string: "http://localhost:\(server.port)/echo")!
|
|
print("Test \(#function) on port \(server.port)")
|
|
var request = URLRequest(url: url)
|
|
request.httpMethod = "POST"
|
|
request.httpBody = testString.data(using: .utf8)
|
|
request.setValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
|
|
let dataTask = session.dataTask(with: request) { (responseBody, rawResponse, error) in
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
XCTAssertNotNil(responseBody)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
XCTAssertEqual(testString, String(data: responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
receivedExpectation.fulfill()
|
|
}
|
|
dataTask.resume()
|
|
self.waitForExpectations(timeout: 10) { (error) in
|
|
if let error = error {
|
|
XCTFail("\(error)")
|
|
}
|
|
}
|
|
server.stop()
|
|
} catch {
|
|
XCTFail("Error listening on port \(0): \(error). Use server.failed(callback:) to handle")
|
|
}
|
|
}
|
|
|
|
func testRequestKeepAliveEchoEndToEnd() {
|
|
let receivedExpectation1 = self.expectation(description: "Received web response 1: \(#function)")
|
|
let receivedExpectation2 = self.expectation(description: "Received web response 2: \(#function)")
|
|
let receivedExpectation3 = self.expectation(description: "Received web response 3: \(#function)")
|
|
let testString1="This is a test"
|
|
let testString2="This is a test, too"
|
|
let testString3="This is also a test"
|
|
|
|
let server = BlueSocketSimpleServer()
|
|
do {
|
|
try server.start(port: 0, webapp: EchoWebApp().serve)
|
|
let session = URLSession(configuration: URLSessionConfiguration.default)
|
|
let url = URL(string: "http://localhost:\(server.port)/echo")!
|
|
print("Test \(#function) on port \(server.port)")
|
|
var request1 = URLRequest(url: url)
|
|
request1.httpMethod = "POST"
|
|
request1.httpBody = testString1.data(using: .utf8)
|
|
request1.setValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
|
|
let dataTask1 = session.dataTask(with: request1) { (responseBody, rawResponse, error) in
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
let headers = response?.allHeaderFields ?? ["":""]
|
|
let connectionHeader: String = headers["Connection"] as? String ?? ""
|
|
let keepAliveHeader = headers["Keep-Alive"]
|
|
XCTAssertEqual(connectionHeader,"Keep-Alive","No Keep-Alive Connection")
|
|
XCTAssertNotNil(keepAliveHeader)
|
|
XCTAssertNotNil(responseBody,"No Keep-Alive Header")
|
|
XCTAssertEqual(server.connectionCount, 1)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
XCTAssertEqual(testString1, String(data: responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
var request2 = URLRequest(url: url)
|
|
request2.httpMethod = "POST"
|
|
request2.httpBody = testString2.data(using: .utf8)
|
|
request2.setValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
let dataTask2 = session.dataTask(with: request2) { (responseBody2, rawResponse2, error2) in
|
|
let response2 = rawResponse2 as? HTTPURLResponse
|
|
XCTAssertNil(error2, "\(error2!.localizedDescription)")
|
|
XCTAssertNotNil(response2)
|
|
let headers = response2?.allHeaderFields ?? ["":""]
|
|
let connectionHeader: String = headers["Connection"] as? String ?? ""
|
|
let keepAliveHeader = headers["Keep-Alive"]
|
|
XCTAssertEqual(connectionHeader,"Keep-Alive","No Keep-Alive Connection")
|
|
XCTAssertNotNil(keepAliveHeader,"No Keep-Alive Header")
|
|
XCTAssertEqual(server.connectionCount, 1)
|
|
XCTAssertNotNil(responseBody2)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response2?.statusCode ?? 0)
|
|
XCTAssertEqual(testString2, String(data: responseBody2 ?? Data(), encoding: .utf8) ?? "Nil")
|
|
var request3 = URLRequest(url: url)
|
|
request3.httpMethod = "POST"
|
|
request3.httpBody = testString3.data(using: .utf8)
|
|
request3.setValue("text/plain", forHTTPHeaderField: "Content-Type")
|
|
let dataTask3 = session.dataTask(with: request3) { (responseBody, rawResponse, error) in
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
let headers = response?.allHeaderFields ?? ["":""]
|
|
let connectionHeader: String = headers["Connection"] as? String ?? ""
|
|
let keepAliveHeader = headers["Keep-Alive"]
|
|
XCTAssertEqual(connectionHeader,"Keep-Alive","No Keep-Alive Connection")
|
|
XCTAssertNotNil(keepAliveHeader,"No Keep-Alive Header")
|
|
XCTAssertEqual(server.connectionCount, 1)
|
|
XCTAssertNotNil(responseBody)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
XCTAssertEqual(testString3, String(data: responseBody ?? Data(), encoding: .utf8) ?? "Nil")
|
|
receivedExpectation3.fulfill()
|
|
}
|
|
dataTask3.resume()
|
|
receivedExpectation2.fulfill()
|
|
}
|
|
dataTask2.resume()
|
|
receivedExpectation1.fulfill()
|
|
}
|
|
dataTask1.resume()
|
|
|
|
self.waitForExpectations(timeout: 10) { (error) in
|
|
if let error = error {
|
|
XCTFail("\(error)")
|
|
}
|
|
}
|
|
//server.stop()
|
|
} catch {
|
|
XCTFail("Error listening on port \(0): \(error). Use server.failed(callback:) to handle")
|
|
}
|
|
}
|
|
|
|
|
|
func testRequestLargeEchoEndToEnd() {
|
|
let receivedExpectation = self.expectation(description: "Received web response \(#function)")
|
|
//Get a file we know exists
|
|
//let currentDirectoryURL = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
|
|
let executableUrl = URL(fileURLWithPath: CommandLine.arguments[0])
|
|
|
|
let testExecutableData = try! Data(contentsOf: executableUrl)
|
|
|
|
var testDataLong = testExecutableData + testExecutableData + testExecutableData + testExecutableData
|
|
let length = testDataLong.count
|
|
let keep = 16385
|
|
let remove = length - keep
|
|
if (remove > 0) {
|
|
testDataLong.removeLast(remove)
|
|
}
|
|
|
|
let testData = Data(testDataLong)
|
|
|
|
let server = BlueSocketSimpleServer()
|
|
do {
|
|
try server.start(port: 0, webapp: EchoWebApp().serve)
|
|
let session = URLSession(configuration: URLSessionConfiguration.default)
|
|
let url = URL(string: "http://localhost:\(server.port)/echo")!
|
|
print("Test \(#function) on port \(server.port)")
|
|
var request = URLRequest(url: url)
|
|
request.httpMethod = "POST"
|
|
request.httpBody = testData
|
|
let dataTask = session.dataTask(with: request) { (responseBody, rawResponse, error) in
|
|
let response = rawResponse as? HTTPURLResponse
|
|
XCTAssertNil(error, "\(error!.localizedDescription)")
|
|
XCTAssertNotNil(response)
|
|
XCTAssertNotNil(responseBody)
|
|
XCTAssertEqual(Int(HTTPResponseStatus.ok.code), response?.statusCode ?? 0)
|
|
XCTAssertEqual(testData, responseBody ?? Data())
|
|
receivedExpectation.fulfill()
|
|
}
|
|
dataTask.resume()
|
|
self.waitForExpectations(timeout: 10) { (error) in
|
|
if let error = error {
|
|
XCTFail("\(error)")
|
|
}
|
|
}
|
|
server.stop()
|
|
} catch {
|
|
XCTFail("Error listening on port \(0): \(error). Use server.failed(callback:) to handle")
|
|
}
|
|
}
|
|
|
|
static var allTests = [
|
|
("testEcho", testEcho),
|
|
("testHello", testHello),
|
|
("testHeaders", testHeaders),
|
|
("testSimpleHello", testSimpleHello),
|
|
("testResponseOK", testResponseOK),
|
|
("testResponseCodes", testResponseCodes),
|
|
("testHelloEndToEnd", testHelloEndToEnd),
|
|
("testSimpleHelloEndToEnd", testSimpleHelloEndToEnd),
|
|
("testRequestEchoEndToEnd", testRequestEchoEndToEnd),
|
|
("testRequestKeepAliveEchoEndToEnd", testRequestKeepAliveEchoEndToEnd),
|
|
("testRequestLargeEchoEndToEnd", testRequestLargeEchoEndToEnd),
|
|
]
|
|
}
|