Skip to content

Commit 5ea6461

Browse files
authored
Merge pull request #1115 from mamabusi/urlProtocolTests
2 parents ce1a76c + 8e8c708 commit 5ea6461

File tree

5 files changed

+209
-93
lines changed

5 files changed

+209
-93
lines changed

Foundation.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
0383A1751D2E558A0052E5D1 /* TestNSStream.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0383A1741D2E558A0052E5D1 /* TestNSStream.swift */; };
11+
03B6F5841F15F339004F25AF /* TestNSURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */; };
1112
1520469B1D8AEABE00D02E36 /* HTTPServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1520469A1D8AEABE00D02E36 /* HTTPServer.swift */; };
1213
159884921DCC877700E3314C /* TestNSHTTPCookieStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */; };
1314
231503DB1D8AEE5D0061694D /* TestNSDecimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231503DA1D8AEE5D0061694D /* TestNSDecimal.swift */; };
@@ -479,6 +480,7 @@
479480

480481
/* Begin PBXFileReference section */
481482
0383A1741D2E558A0052E5D1 /* TestNSStream.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSStream.swift; sourceTree = "<group>"; };
483+
03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSURLProtocol.swift; sourceTree = "<group>"; };
482484
1520469A1D8AEABE00D02E36 /* HTTPServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPServer.swift; sourceTree = "<group>"; };
483485
159884911DCC877700E3314C /* TestNSHTTPCookieStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSHTTPCookieStorage.swift; sourceTree = "<group>"; };
484486
22B9C1E01C165D7A00DECFF9 /* TestNSDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSDate.swift; sourceTree = "<group>"; };
@@ -1484,6 +1486,7 @@
14841486
CC5249BF1D341D23007CB54D /* TestUnitConverter.swift */,
14851487
D4FE895A1D703D1100DA7986 /* TestURLRequest.swift */,
14861488
5B6F17961C48631C00935030 /* TestUtils.swift */,
1489+
03B6F5831F15F339004F25AF /* TestNSURLProtocol.swift */,
14871490
);
14881491
name = Tests;
14891492
sourceTree = "<group>";
@@ -2372,6 +2375,7 @@
23722375
BF8E65311DC3B3CB005AB5C3 /* TestNotification.swift in Sources */,
23732376
63DCE9D41EAA432400E9CB02 /* TestISO8601DateFormatter.swift in Sources */,
23742377
EA01AAEC1DA839C4008F4E07 /* TestProgress.swift in Sources */,
2378+
03B6F5841F15F339004F25AF /* TestNSURLProtocol.swift in Sources */,
23752379
5B13B3411C582D4C00651CE2 /* TestNSRegularExpression.swift in Sources */,
23762380
5B13B3491C582D4C00651CE2 /* TestNSTimeZone.swift in Sources */,
23772381
5B13B34B1C582D4C00651CE2 /* TestNSURLRequest.swift in Sources */,

TestFoundation/HTTPServer.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import Dispatch
1717
#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
1818
import Foundation
1919
import Glibc
20+
import XCTest
2021
#else
2122
import CoreFoundation
2223
import SwiftFoundation
2324
import Darwin
25+
import SwiftXCTest
2426
#endif
2527

2628
public let globalDispatchQueue = DispatchQueue.global()
@@ -394,3 +396,39 @@ public class ServerSemaphore {
394396
dispatchSemaphore.signal()
395397
}
396398
}
399+
400+
class LoopbackServerTest : XCTestCase {
401+
static var serverPort: Int = -1
402+
403+
override class func setUp() {
404+
super.setUp()
405+
func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
406+
let start = 21961
407+
for port in start...(start+100) { //we must find at least one port to bind
408+
do {
409+
serverPort = port
410+
let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
411+
try test.start(started: condition)
412+
try test.readAndRespond()
413+
test.stop()
414+
} catch let e as ServerError {
415+
if e.operation == "bind" { continue }
416+
throw e
417+
}
418+
}
419+
}
420+
421+
let serverReady = ServerSemaphore()
422+
globalDispatchQueue.async {
423+
do {
424+
try runServer(with: serverReady)
425+
426+
} catch {
427+
XCTAssertTrue(true)
428+
return
429+
}
430+
}
431+
432+
serverReady.wait()
433+
}
434+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// This source file is part of the Swift.org open source project
2+
//
3+
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
4+
// Licensed under Apache License v2.0 with Runtime Library Exception
5+
//
6+
// See http://swift.org/LICENSE.txt for license information
7+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
8+
//
9+
#if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
10+
import Foundation
11+
import XCTest
12+
#else
13+
import SwiftFoundation
14+
import SwiftXCTest
15+
#endif
16+
17+
class TestNSURLProtocol : LoopbackServerTest {
18+
19+
static var allTests: [(String, (TestNSURLProtocol) -> () throws -> Void)] {
20+
return [
21+
("test_interceptResponse", test_interceptResponse),
22+
("test_interceptRequest", test_interceptRequest),
23+
("test_multipleCustomProtocols", test_multipleCustomProtocols),
24+
("test_customProtocolResponseWithDelegate", test_customProtocolResponseWithDelegate),
25+
("test_customProtocolSetDataInResponseWithDelegate", test_customProtocolSetDataInResponseWithDelegate),
26+
]
27+
}
28+
29+
func test_interceptResponse() {
30+
let urlString = "http://127.0.0.1:\(TestNSURLProtocol.serverPort)/USA"
31+
let url = URL(string: urlString)!
32+
let config = URLSessionConfiguration.default
33+
config.protocolClasses = [CustomProtocol.self]
34+
config.timeoutIntervalForRequest = 8
35+
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
36+
let expect = expectation(description: "GET \(urlString): with a custom protocol")
37+
let task = session.dataTask(with: url) { data, response, error in
38+
defer { expect.fulfill() }
39+
if let e = error as? URLError {
40+
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
41+
return
42+
}
43+
let httpResponse = response as! HTTPURLResponse?
44+
XCTAssertEqual(429, httpResponse!.statusCode, "HTTP response code is not 429")
45+
}
46+
task.resume()
47+
waitForExpectations(timeout: 12)
48+
}
49+
50+
func test_interceptRequest() {
51+
let urlString = "ssh://127.0.0.1:\(TestNSURLProtocol.serverPort)/USA"
52+
let url = URL(string: urlString)!
53+
let config = URLSessionConfiguration.default
54+
config.protocolClasses = [InterceptableRequest.self]
55+
config.timeoutIntervalForRequest = 8
56+
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
57+
let expect = expectation(description: "GET \(urlString): with a custom protocol")
58+
let task = session.dataTask(with: url) { data, response, error in
59+
defer { expect.fulfill() }
60+
if let e = error as? URLError {
61+
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
62+
return
63+
}
64+
let httpResponse = response as! HTTPURLResponse?
65+
let responseURL = URL(string: "http://google.com")
66+
XCTAssertEqual(responseURL, httpResponse?.url, "Unexpected url")
67+
XCTAssertEqual(200, httpResponse!.statusCode, "HTTP response code is not 200")
68+
}
69+
task.resume()
70+
waitForExpectations(timeout: 12)
71+
}
72+
73+
func test_multipleCustomProtocols() {
74+
let urlString = "http://127.0.0.1:\(TestNSURLProtocol.serverPort)/Nepal"
75+
let url = URL(string: urlString)!
76+
let config = URLSessionConfiguration.default
77+
config.protocolClasses = [InterceptableRequest.self, CustomProtocol.self]
78+
let expect = expectation(description: "GET \(urlString): with a custom protocol")
79+
let session = URLSession(configuration: config)
80+
let task = session.dataTask(with: url) { data, response, error in
81+
defer { expect.fulfill() }
82+
if let e = error as? URLError {
83+
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
84+
return
85+
}
86+
let httpResponse = response as! HTTPURLResponse
87+
print(httpResponse.statusCode)
88+
XCTAssertEqual(429, httpResponse.statusCode, "Status code is not 429")
89+
}
90+
task.resume()
91+
waitForExpectations(timeout: 12)
92+
}
93+
94+
func test_customProtocolResponseWithDelegate() {
95+
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
96+
let url = URL(string: urlString)!
97+
let d = DataTask(with: expectation(description: "GET \(urlString): with a custom protocol and delegate"), protocolClasses: [CustomProtocol.self])
98+
d.responseReceivedExpectation = expectation(description: "GET \(urlString): response received")
99+
d.run(with: url)
100+
waitForExpectations(timeout: 12)
101+
}
102+
103+
func test_customProtocolSetDataInResponseWithDelegate() {
104+
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
105+
let url = URL(string: urlString)!
106+
let d = DataTask(with: expectation(description: "GET \(urlString): with a custom protocol and delegate"), protocolClasses: [CustomProtocol.self])
107+
d.run(with: url)
108+
waitForExpectations(timeout: 12)
109+
if !d.error {
110+
XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
111+
}
112+
}
113+
}
114+
115+
class InterceptableRequest : URLProtocol {
116+
117+
override class func canInit(with request: URLRequest) -> Bool {
118+
return request.url?.scheme == "ssh"
119+
}
120+
121+
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
122+
return request
123+
}
124+
125+
override func startLoading() {
126+
let urlString = "http://google.com"
127+
let url = URL(string: urlString)!
128+
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: [:])
129+
self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
130+
self.client?.urlProtocolDidFinishLoading(self)
131+
132+
}
133+
134+
override func stopLoading() {
135+
return
136+
}
137+
}
138+
139+
class CustomProtocol : URLProtocol {
140+
141+
override class func canInit(with request: URLRequest) -> Bool {
142+
return true
143+
}
144+
145+
func sendResponse(statusCode: Int, headers: [String: String] = [:], data: Data) {
146+
let response = HTTPURLResponse(url: self.request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: headers)
147+
let capital = "Kathmandu"
148+
let data = capital.data(using: String.Encoding.utf8)
149+
self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
150+
self.client?.urlProtocol(self, didLoad: data!)
151+
self.client?.urlProtocolDidFinishLoading(self)
152+
}
153+
154+
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
155+
return request
156+
}
157+
158+
override func startLoading() {
159+
sendResponse(statusCode: 429, data: Data())
160+
}
161+
162+
override func stopLoading() {
163+
return
164+
}
165+
}

TestFoundation/TestNSURLSession.swift

Lines changed: 1 addition & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515
import SwiftXCTest
1616
#endif
1717

18-
class TestURLSession : XCTestCase {
19-
20-
static var serverPort: Int = -1
18+
class TestURLSession : LoopbackServerTest {
2119

2220
static var allTests: [(String, (TestURLSession) -> () throws -> Void)] {
2321
return [
@@ -37,8 +35,6 @@ class TestURLSession : XCTestCase {
3735
("test_verifyRequestHeaders", test_verifyRequestHeaders),
3836
("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
3937
("test_timeoutInterval", test_timeoutInterval),
40-
("test_customProtocol", test_customProtocol),
41-
("test_customProtocolResponseWithDelegate", test_customProtocolResponseWithDelegate),
4238
("test_httpRedirection", test_httpRedirection),
4339
("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
4440
("test_http0_9SimpleResponses", test_http0_9SimpleResponses),
@@ -48,38 +44,6 @@ class TestURLSession : XCTestCase {
4844
]
4945
}
5046

51-
override class func setUp() {
52-
super.setUp()
53-
func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
54-
let start = 21961
55-
for port in start...(start+100) { //we must find at least one port to bind
56-
do {
57-
serverPort = port
58-
let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
59-
try test.start(started: condition)
60-
try test.readAndRespond()
61-
test.stop()
62-
} catch let e as ServerError {
63-
if e.operation == "bind" { continue }
64-
throw e
65-
}
66-
}
67-
}
68-
69-
let serverReady = ServerSemaphore()
70-
globalDispatchQueue.async {
71-
do {
72-
try runServer(with: serverReady)
73-
74-
} catch {
75-
XCTAssertTrue(true)
76-
return
77-
}
78-
}
79-
80-
serverReady.wait()
81-
}
82-
8347
func test_dataTaskWithURL() {
8448
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Nepal"
8549
let url = URL(string: urlString)!
@@ -338,37 +302,6 @@ class TestURLSession : XCTestCase {
338302
waitForExpectations(timeout: 30)
339303
}
340304

341-
func test_customProtocol () {
342-
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/USA"
343-
let url = URL(string: urlString)!
344-
let config = URLSessionConfiguration.default
345-
config.protocolClasses = [CustomProtocol.self]
346-
config.timeoutIntervalForRequest = 8
347-
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
348-
let expect = expectation(description: "GET \(urlString): with a custom protocol")
349-
350-
let task = session.dataTask(with: url) { data, response, error in
351-
defer { expect.fulfill() }
352-
if let e = error as? URLError {
353-
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
354-
return
355-
}
356-
let httpResponse = response as! HTTPURLResponse?
357-
XCTAssertEqual(429, httpResponse!.statusCode, "HTTP response code is not 429")
358-
}
359-
task.resume()
360-
waitForExpectations(timeout: 12)
361-
}
362-
363-
func test_customProtocolResponseWithDelegate() {
364-
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/Peru"
365-
let url = URL(string: urlString)!
366-
let d = DataTask(with: expectation(description: "GET \(urlString): with a custom protocol and delegate"), protocolClasses: [CustomProtocol.self])
367-
d.responseReceivedExpectation = expectation(description: "GET \(urlString): response received")
368-
d.run(with: url)
369-
waitForExpectations(timeout: 12)
370-
}
371-
372305
func test_httpRedirection() {
373306
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
374307
let url = URL(string: urlString)!
@@ -629,31 +562,6 @@ extension DownloadTask : URLSessionTaskDelegate {
629562
}
630563
}
631564

632-
class CustomProtocol : URLProtocol {
633-
634-
override class func canInit(with request: URLRequest) -> Bool {
635-
return true
636-
}
637-
638-
func sendResponse(statusCode: Int, headers: [String: String] = [:], data: Data) {
639-
let response = HTTPURLResponse(url: self.request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: headers)
640-
self.client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: .notAllowed)
641-
self.client?.urlProtocolDidFinishLoading(self)
642-
}
643-
644-
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
645-
return request
646-
}
647-
648-
override func startLoading() {
649-
sendResponse(statusCode: 429, data: Data())
650-
}
651-
652-
override func stopLoading() {
653-
return
654-
}
655-
}
656-
657565
class HTTPRedirectionDataTask : NSObject {
658566
let dataTaskExpectation: XCTestExpectation!
659567
var session: URLSession! = nil

TestFoundation/main.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ XCTMain([
8181
testCase(TestNSURL.allTests),
8282
testCase(TestNSURLComponents.allTests),
8383
testCase(TestNSURLCredential.allTests),
84+
testCase(TestNSURLProtocol.allTests),
8485
testCase(TestNSURLRequest.allTests),
8586
testCase(TestURLRequest.allTests),
8687
testCase(TestNSURLResponse.allTests),

0 commit comments

Comments
 (0)