Skip to content

Commit 42d0cf6

Browse files
authored
Merge pull request #689 from pushkarnk/task-cancel
2 parents dc20612 + 164be73 commit 42d0cf6

File tree

2 files changed

+47
-8
lines changed

2 files changed

+47
-8
lines changed

Foundation/NSURLSession/NSURLSessionTask.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,18 @@ open class URLSessionTask : NSObject, NSCopying {
194194
* cases, the task may signal other work before it acknowledges the
195195
* cancelation. -cancel may be sent to a task that has been suspended.
196196
*/
197-
open func cancel() { NSUnimplemented() }
198-
197+
open func cancel() {
198+
workQueue.sync {
199+
guard self.state == .running || self.state == .suspended else { return }
200+
self.state = .canceling
201+
self.workQueue.async {
202+
self.internalState = .transferFailed
203+
let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil))
204+
self.completeTask(withError: urlError)
205+
}
206+
}
207+
}
208+
199209
/*
200210
* The current state of the task within the session.
201211
*/
@@ -866,7 +876,7 @@ extension URLSessionTask {
866876
}
867877
func completeTask(withError error: Error) {
868878
self.error = error
869-
879+
870880
guard case .transferFailed = internalState else {
871881
fatalError("Trying to complete the task, but its transfer isn't complete / failed.")
872882
}

TestFoundation/TestNSURLSession.swift

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class TestURLSession : XCTestCase {
3232
("test_finishTaskAndInvalidate", test_finishTasksAndInvalidate),
3333
("test_taskError", test_taskError),
3434
("test_taskCopy", test_taskCopy),
35+
("test_cancelTask", test_cancelTask),
3536
]
3637
}
3738

@@ -297,6 +298,26 @@ class TestURLSession : XCTestCase {
297298

298299
XCTAssert(task.isEqual(task.copy()))
299300
}
301+
302+
func test_cancelTask() {
303+
let serverReady = ServerSemaphore()
304+
globalDispatchQueue.async {
305+
do {
306+
try self.runServer(with: serverReady)
307+
} catch {
308+
XCTAssertTrue(true)
309+
return
310+
}
311+
}
312+
serverReady.wait()
313+
let url = URL(string: "http://127.0.0.1:\(serverPort)/Peru")!
314+
let d = DataTask(with: expectation(description: "Task to be canceled"))
315+
d.cancelExpectation = expectation(description: "URLSessionTask wasn't canceled")
316+
d.run(with: url)
317+
d.cancel()
318+
waitForExpectations(timeout: 12)
319+
}
320+
300321
}
301322

302323
class SessionDelegate: NSObject, URLSessionDelegate {
@@ -314,6 +335,8 @@ class DataTask : NSObject {
314335
var capital = "unknown"
315336
var session: URLSession! = nil
316337
var task: URLSessionDataTask! = nil
338+
var cancelExpectation: XCTestExpectation?
339+
317340
public var error = false
318341

319342
init(with expectation: XCTestExpectation) {
@@ -335,20 +358,26 @@ class DataTask : NSObject {
335358
task = session.dataTask(with: url)
336359
task.resume()
337360
}
361+
362+
func cancel() {
363+
task.cancel()
364+
}
338365
}
339366

340367
extension DataTask : URLSessionDataDelegate {
341-
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
342-
capital = String(data: data, encoding: String.Encoding.utf8)!
343-
dataTaskExpectation.fulfill()
344-
}
368+
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
369+
capital = String(data: data, encoding: String.Encoding.utf8)!
370+
dataTaskExpectation.fulfill()
371+
}
345372
}
346373

347374
extension DataTask : URLSessionTaskDelegate {
348375
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
349376
guard let e = error as? URLError else { return }
350-
XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
351377
dataTaskExpectation.fulfill()
378+
if let cancellation = cancelExpectation {
379+
cancellation.fulfill()
380+
}
352381
self.error = true
353382
}
354383
}

0 commit comments

Comments
 (0)