Merge pull request #1062 from ddunn2/urlSessionServer
diff --git a/TestFoundation/TestNSURLSession.swift b/TestFoundation/TestNSURLSession.swift
index 9759338..096ddae 100644
--- a/TestFoundation/TestNSURLSession.swift
+++ b/TestFoundation/TestNSURLSession.swift
@@ -16,9 +16,9 @@
#endif
class TestURLSession : XCTestCase {
-
- var serverPort: Int = -1
-
+
+ static var serverPort: Int = -1
+
static var allTests: [(String, (TestURLSession) -> () throws -> Void)] {
return [
("test_dataTaskWithURL", test_dataTaskWithURL),
@@ -37,39 +37,45 @@
("test_verifyRequestHeaders", test_verifyRequestHeaders),
("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
("test_timeoutInterval", test_timeoutInterval),
- ("test_customProtocol", test_customProtocol),
- ("test_httpRedirection", test_httpRedirection),
+ ("test_customProtocol", test_customProtocol),
+ ("test_httpRedirection", test_httpRedirection),
]
}
-
- private func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
- let start = 21961
- for port in start...(start+100) { //we must find at least one port to bind
- do {
- serverPort = port
- let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
- try test.start(started: condition)
- try test.readAndRespond()
- test.stop()
- } catch let e as ServerError {
- if e.operation == "bind" { continue }
- throw e
+
+ override class func setUp() {
+ super.setUp()
+ func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
+ let start = 21961
+ for port in start...(start+100) { //we must find at least one port to bind
+ do {
+ serverPort = port
+ let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
+ try test.start(started: condition)
+ try test.readAndRespond()
+ test.stop()
+ } catch let e as ServerError {
+ if e.operation == "bind" { continue }
+ throw e
+ }
}
}
- }
-
- func test_dataTaskWithURL() {
+
let serverReady = ServerSemaphore()
globalDispatchQueue.async {
do {
- try self.runServer(with: serverReady)
+ try runServer(with: serverReady)
+
} catch {
XCTAssertTrue(true)
return
}
}
+
serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/Nepal"
+ }
+
+ func test_dataTaskWithURL() {
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
let url = URL(string: urlString)!
let d = DataTask(with: expectation(description: "data task"))
d.run(with: url)
@@ -78,19 +84,9 @@
XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
}
}
-
+
func test_dataTaskWithURLCompletionHandler() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/USA"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/USA"
let url = URL(string: urlString)!
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -110,19 +106,9 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_dataTaskWithURLRequest() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/Peru"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
let urlRequest = URLRequest(url: URL(string: urlString)!)
let d = DataTask(with: expectation(description: "data task"))
d.run(with: urlRequest)
@@ -131,19 +117,9 @@
XCTAssertEqual(d.capital, "Lima", "test_dataTaskWithURLRequest returned an unexpected result")
}
}
-
+
func test_dataTaskWithURLRequestCompletionHandler() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/Italy"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Italy"
let urlRequest = URLRequest(url: URL(string: urlString)!)
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -163,59 +139,29 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_downloadTaskWithURL() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/country.txt"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
let url = URL(string: urlString)!
let d = DownloadTask(with: expectation(description: "download task with delegate"))
d.run(with: url)
waitForExpectations(timeout: 12)
}
-
+
func test_downloadTaskWithURLRequest() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/country.txt"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
let urlRequest = URLRequest(url: URL(string: urlString)!)
let d = DownloadTask(with: expectation(description: "download task with delegate"))
d.run(with: urlRequest)
waitForExpectations(timeout: 12)
}
-
+
func test_downloadTaskWithRequestAndHandler() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
let expect = expectation(description: "download task with handler")
- let req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/country.txt")!)
+ let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt")!)
let task = session.downloadTask(with: req) { (_, _, error) -> Void in
XCTAssertNil(error as? URLError, "error = \(error as! URLError)")
expect.fulfill()
@@ -223,23 +169,13 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_downloadTaskWithURLAndHandler() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
let expect = expectation(description: "download task with handler")
- let req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/country.txt")!)
+ let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt")!)
let task = session.downloadTask(with: req) { (_, _, error) -> Void in
if let e = error as? URLError {
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
@@ -249,11 +185,11 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_finishTasksAndInvalidate() {
let invalidateExpectation = expectation(description: "URLSession wasn't invalidated")
let delegate = SessionDelegate(invalidateExpectation: invalidateExpectation)
- let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
+ let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
delegate: delegate, delegateQueue: nil)
let completionExpectation = expectation(description: "dataTask completion block wasn't called")
@@ -264,75 +200,56 @@
session.finishTasksAndInvalidate()
waitForExpectations(timeout: 12)
}
-
+
func test_taskError() {
- let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
+ let url = URL(string: "http://127.0.0.1:-1/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: nil)
let completionExpectation = expectation(description: "dataTask completion block wasn't called")
let task = session.dataTask(with: url) { result in
let error = result.2 as? URLError
+
XCTAssertNotNil(error)
XCTAssertEqual(error?.code, .badURL)
completionExpectation.fulfill()
}
//should result in Bad URL error
task.resume()
-
+
waitForExpectations(timeout: 5) { error in
XCTAssertNil(error)
-
+
XCTAssertNotNil(task.error)
XCTAssertEqual((task.error as? URLError)?.code, .badURL)
}
}
-
+
func test_taskCopy() {
- let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
+ let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: nil)
let task = session.dataTask(with: url)
-
+
XCTAssert(task.isEqual(task.copy()))
}
-
+
func test_cancelTask() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let url = URL(string: "http://127.0.0.1:\(serverPort)/Peru")!
+ let url = URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!
let d = DataTask(with: expectation(description: "Task to be canceled"))
d.cancelExpectation = expectation(description: "URLSessionTask wasn't canceled")
d.run(with: url)
d.cancel()
waitForExpectations(timeout: 12)
}
-
+
func test_verifyRequestHeaders() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 5
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
var expect = expectation(description: "download task with handler")
- var req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/requestHeaders")!)
+ var req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders")!)
let headers = ["header1": "value1"]
req.httpMethod = "POST"
req.allHTTPHeaderFields = headers
@@ -345,30 +262,20 @@
XCTAssertNotNil(headers.range(of: "header1: value1"))
}
task.resume()
-
+ req.allHTTPHeaderFields = nil
waitForExpectations(timeout: 30)
}
-
+
// Verify httpAdditionalHeaders from session configuration are added to the request
// and whether it is overriden by Request.allHTTPHeaderFields.
func test_verifyHttpAdditionalHeaders() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 5
config.httpAdditionalHeaders = ["header2": "svalue2", "header3": "svalue3"]
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
var expect = expectation(description: "download task with handler")
- var req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/requestHeaders")!)
+ var req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/requestHeaders")!)
let headers = ["header1": "rvalue1", "header2": "rvalue2"]
req.httpMethod = "POST"
req.allHTTPHeaderFields = headers
@@ -385,70 +292,40 @@
waitForExpectations(timeout: 30)
}
-
+
func test_taskTimeout() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady, startDelay: 3, sendDelay: 3, bodyChunks: 3)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 5
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
var expect = expectation(description: "download task with handler")
- let req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/Peru")!)
+ let req = URLRequest(url: URL(string: "http://127.0.0.1:\(TestURLSession.serverPort)/Peru")!)
var task = session.dataTask(with: req) { (data, _, error) -> Void in
defer { expect.fulfill() }
XCTAssertNil(error as? URLError, "error = \(error as! URLError)")
}
task.resume()
-
+
waitForExpectations(timeout: 30)
}
-
+
func test_timeoutInterval() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady, startDelay: 3, sendDelay: 5, bodyChunks: 3)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 10
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
var expect = expectation(description: "download task with handler")
- var req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/Peru")!)
+ var req = URLRequest(url: URL(string: "http://127.0.0.1:-1/Peru")!)
req.timeoutInterval = 1
var task = session.dataTask(with: req) { (data, _, error) -> Void in
defer { expect.fulfill() }
XCTAssertNotNil(error)
}
task.resume()
-
+
waitForExpectations(timeout: 30)
}
-
+
func test_customProtocol () {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/USA"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/USA"
let url = URL(string: urlString)!
let config = URLSessionConfiguration.default
config.protocolClasses = [CustomProtocol.self]
@@ -467,19 +344,9 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_httpRedirection() {
- let serverReady = ServerSemaphore()
- globalDispatchQueue.async {
- do {
- try self.runServer(with: serverReady)
- } catch {
- XCTAssertTrue(true)
- return
- }
- }
- serverReady.wait()
- let urlString = "http://127.0.0.1:\(serverPort)/UnitedStates"
+ let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
let url = URL(string: urlString)!
let d = HTTPRedirectionDataTask(with: expectation(description: "data task"))
d.run(with: url)
@@ -503,13 +370,13 @@
var session: URLSession! = nil
var task: URLSessionDataTask! = nil
var cancelExpectation: XCTestExpectation?
-
+
public var error = false
-
+
init(with expectation: XCTestExpectation) {
- dataTaskExpectation = expectation
+ dataTaskExpectation = expectation
}
-
+
func run(with request: URLRequest) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -517,7 +384,7 @@
task = session.dataTask(with: request)
task.resume()
}
-
+
func run(with url: URL) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -525,7 +392,7 @@
task = session.dataTask(with: url)
task.resume()
}
-
+
func cancel() {
task.cancel()
}
@@ -539,13 +406,13 @@
extension DataTask : URLSessionTaskDelegate {
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
- dataTaskExpectation.fulfill()
- guard (error as? URLError) != nil else { return }
- if let cancellation = cancelExpectation {
- cancellation.fulfill()
- }
- self.error = true
- }
+ dataTaskExpectation.fulfill()
+ guard (error as? URLError) != nil else { return }
+ if let cancellation = cancelExpectation {
+ cancellation.fulfill()
+ }
+ self.error = true
+ }
}
class DownloadTask : NSObject {
@@ -553,11 +420,11 @@
let dwdExpectation: XCTestExpectation!
var session: URLSession! = nil
var task: URLSessionDownloadTask! = nil
-
+
init(with expectation: XCTestExpectation) {
dwdExpectation = expectation
}
-
+
func run(with url: URL) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -565,7 +432,7 @@
task = session.downloadTask(with: url)
task.resume()
}
-
+
func run(with urlRequest: URLRequest) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -576,12 +443,12 @@
}
extension DownloadTask : URLSessionDownloadDelegate {
-
+
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64,
totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) -> Void {
self.totalBytesWritten = totalBytesWritten
}
-
+
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
do {
let attr = try FileManager.default.attributesOfItem(atPath: location.path)
@@ -590,37 +457,37 @@
XCTFail("Unable to calculate size of the downloaded file")
}
dwdExpectation.fulfill()
- }
+ }
}
extension DownloadTask : URLSessionTaskDelegate {
- public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
- guard let e = error as? URLError else { return }
- XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
- dwdExpectation.fulfill()
- }
+ public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+ guard let e = error as? URLError else { return }
+ XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
+ dwdExpectation.fulfill()
+ }
}
class CustomProtocol : URLProtocol {
-
+
override class func canInit(with request: URLRequest) -> Bool {
return true
}
-
+
func sendResponse(statusCode: Int, headers: [String: String] = [:], data: Data) {
let response = HTTPURLResponse(url: self.request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: headers)
self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
self.client?.urlProtocolDidFinishLoading(self)
}
-
+
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
-
+
override func startLoading() {
sendResponse(statusCode: 429, data: Data())
}
-
+
override func stopLoading() {
return
}
@@ -631,13 +498,13 @@
var session: URLSession! = nil
var task: URLSessionDataTask! = nil
var cancelExpectation: XCTestExpectation?
-
+
public var error = false
-
+
init(with expectation: XCTestExpectation) {
dataTaskExpectation = expectation
}
-
+
func run(with request: URLRequest) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -645,7 +512,7 @@
task = session.dataTask(with: request)
task.resume()
}
-
+
func run(with url: URL) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -653,7 +520,7 @@
task = session.dataTask(with: url)
task.resume()
}
-
+
func cancel() {
task.cancel()
}
@@ -662,7 +529,7 @@
extension HTTPRedirectionDataTask : URLSessionDataDelegate {
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
guard let httpresponse = response as? HTTPURLResponse else { fatalError() }
- XCTAssertNotNil(response)
+ XCTAssertNotNil(response)
XCTAssertEqual(200, httpresponse.statusCode, "HTTP response code is not 200")
}
}
@@ -676,7 +543,7 @@
}
self.error = true
}
-
+
public func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
XCTAssertNotNil(response)
XCTAssertEqual(302, response.statusCode, "HTTP response code is not 302")