Skip to content

Commit e3c5d7a

Browse files
authored
Merge pull request #913 from naithar/URLSession-test
2 parents 7dbef6d + bb9d10c commit e3c5d7a

File tree

2 files changed

+84
-14
lines changed

2 files changed

+84
-14
lines changed

TestFoundation/HTTPServer.swift

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,33 @@ class _TCPSocket {
9292
_ = try attempt("read", valid: isNotNegative, CInt(read(connectionSocket, &buffer, 4096)))
9393
return String(cString: &buffer)
9494
}
95+
96+
func split(_ str: String, _ count: Int) -> [String] {
97+
return stride(from: 0, to: str.characters.count, by: count).map { i -> String in
98+
let startIndex = str.index(str.startIndex, offsetBy: i)
99+
let endIndex = str.index(startIndex, offsetBy: count, limitedBy: str.endIndex) ?? str.endIndex
100+
return str[startIndex..<endIndex]
101+
}
102+
}
95103

96-
func writeData(data: String) throws {
97-
var bytes = Array(data.utf8)
98-
_ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, data.utf8.count)))
104+
func writeData(header: String, body: String, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
105+
var header = Array(header.utf8)
106+
_ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &header, header.count)))
107+
108+
if let sendDelay = sendDelay, let bodyChunks = bodyChunks {
109+
let count = max(1, Int(Double(body.utf8.count) / Double(bodyChunks)))
110+
let texts = split(body, count)
111+
112+
for item in texts {
113+
sleep(UInt32(sendDelay))
114+
var bytes = Array(item.utf8)
115+
print(item)
116+
_ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, bytes.count)))
117+
}
118+
} else {
119+
var bytes = Array(body.utf8)
120+
_ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, bytes.count)))
121+
}
99122
}
100123

101124
func shutdown() {
@@ -128,8 +151,24 @@ class _HTTPServer {
128151
return _HTTPRequest(request: try socket.readData())
129152
}
130153

131-
public func respond(with response: _HTTPResponse) throws {
132-
try socket.writeData(data: response.description)
154+
public func respond(with response: _HTTPResponse, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
155+
let semaphore = DispatchSemaphore(value: 0)
156+
let deadlineTime: DispatchTime
157+
158+
if let startDelay = startDelay {
159+
deadlineTime = .now() + .seconds(Int(startDelay))
160+
} else {
161+
deadlineTime = .now()
162+
}
163+
164+
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
165+
do {
166+
try self.socket.writeData(header: response.header, body: response.body, sendDelay: sendDelay, bodyChunks: bodyChunks)
167+
semaphore.signal()
168+
} catch { }
169+
}
170+
semaphore.wait()
171+
133172
}
134173
}
135174

@@ -160,17 +199,17 @@ struct _HTTPResponse {
160199
}
161200
private let responseCode: Response
162201
private let headers: String
163-
private let body: String
202+
public let body: String
164203

165204
public init(response: Response, headers: String = _HTTPUtils.EMPTY, body: String) {
166205
self.responseCode = response
167206
self.headers = headers
168207
self.body = body
169208
}
170209

171-
public var description: String {
210+
public var header: String {
172211
let statusLine = _HTTPUtils.VERSION + _HTTPUtils.SPACE + "\(responseCode.rawValue)" + _HTTPUtils.SPACE + "\(responseCode)"
173-
return statusLine + (headers != _HTTPUtils.EMPTY ? _HTTPUtils.CRLF + headers : _HTTPUtils.EMPTY) + _HTTPUtils.CRLF2 + body
212+
return statusLine + (headers != _HTTPUtils.EMPTY ? _HTTPUtils.CRLF + headers : _HTTPUtils.EMPTY) + _HTTPUtils.CRLF2
174213
}
175214
}
176215

@@ -181,18 +220,24 @@ public class TestURLSessionServer {
181220
"USA":"Washington, D.C.",
182221
"country.txt": "A country is a region that is identified as a distinct national entity in political geography"]
183222
let httpServer: _HTTPServer
223+
let startDelay: TimeInterval?
224+
let sendDelay: TimeInterval?
225+
let bodyChunks: Int?
184226

185-
public init (port: UInt16) throws {
227+
public init (port: UInt16, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
186228
httpServer = try _HTTPServer.create(port: port)
229+
self.startDelay = startDelay
230+
self.sendDelay = sendDelay
231+
self.bodyChunks = bodyChunks
187232
}
188233
public func start(started: ServerSemaphore) throws {
189234
started.signal()
190235
try httpServer.listen(notify: started)
191236
}
192237

193238
public func readAndRespond() throws {
194-
try httpServer.respond(with: process(request: httpServer.request()))
195-
}
239+
try httpServer.respond(with: process(request: httpServer.request()), startDelay: self.startDelay, sendDelay: self.sendDelay, bodyChunks: self.bodyChunks)
240+
}
196241

197242
func process(request: _HTTPRequest) -> _HTTPResponse {
198243
if request.method == .GET {

TestFoundation/TestNSURLSession.swift

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@ class TestURLSession : XCTestCase {
3333
("test_taskError", test_taskError),
3434
("test_taskCopy", test_taskCopy),
3535
("test_cancelTask", test_cancelTask),
36+
// ("test_taskTimeout", test_taskTimeout),
3637
]
3738
}
3839

39-
private func runServer(with condition: ServerSemaphore) throws {
40+
private func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
4041
let start = 21961
4142
for port in start...(start+100) { //we must find at least one port to bind
4243
do {
4344
serverPort = port
44-
let test = try TestURLSessionServer(port: UInt16(port))
45+
let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
4546
try test.start(started: condition)
4647
try test.readAndRespond()
4748
test.stop()
@@ -317,7 +318,31 @@ class TestURLSession : XCTestCase {
317318
d.cancel()
318319
waitForExpectations(timeout: 12)
319320
}
320-
321+
322+
func test_taskTimeout() {
323+
let serverReady = ServerSemaphore()
324+
globalDispatchQueue.async {
325+
do {
326+
try self.runServer(with: serverReady, startDelay: 3, sendDelay: 3, bodyChunks: 3)
327+
} catch {
328+
XCTAssertTrue(true)
329+
return
330+
}
331+
}
332+
serverReady.wait()
333+
let config = URLSessionConfiguration.default
334+
config.timeoutIntervalForRequest = 5
335+
let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
336+
var expect = expectation(description: "download task with handler")
337+
let req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/Peru")!)
338+
var task = session.dataTask(with: req) { (data, _, error) -> Void in
339+
defer { expect.fulfill() }
340+
XCTAssertNil(error)
341+
}
342+
task.resume()
343+
344+
waitForExpectations(timeout: 30)
345+
}
321346
}
322347

323348
class SessionDelegate: NSObject, URLSessionDelegate {

0 commit comments

Comments
 (0)