Skip to content

Implementation of URLSessionTask '.error', NSCopying #713

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Docs/Status.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ There is no _Complete_ status for test coverage because there are always additio
| `URLSession` | Mostly Complete | Incomplete | `shared`, invalidation, resetting, flushing, getting tasks, and others remain unimplemented |
| `URLSessionConfiguration` | Mostly Complete | Incomplete | `ephemeral` and `background(withIdentifier:)` remain unimplemented |
| `URLSessionDelegate` | Complete | N/A | |
| `URLSessionTask` | Mostly Complete | Incomplete | `NSCopying`, `cancel()`, `error`, `createTransferState(url:)` with streams, and others remain unimplemented |
| `URLSessionTask` | Mostly Complete | Incomplete | `cancel()`, `createTransferState(url:)` with streams, and others remain unimplemented |
| `URLSessionDataTask` | Complete | Incomplete | |
| `URLSessionUploadTask` | Complete | None | |
| `URLSessionDownloadTask` | Incomplete | Incomplete | `cancel(byProducingResumeData:)` remains unimplemented |
Expand Down
13 changes: 9 additions & 4 deletions Foundation/NSURLSession/NSURLSessionTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ open class URLSessionTask : NSObject, NSCopying {
}

open func copy(with zone: NSZone?) -> Any {
NSUnimplemented()
return self
}

/// An identifier for this task, assigned by and unique to the owning session
Expand Down Expand Up @@ -221,7 +221,10 @@ open class URLSessionTask : NSObject, NSCopying {
* The error, if any, delivered via -URLSession:task:didCompleteWithError:
* This property will be nil in the event that no error occured.
*/
/*@NSCopying*/ open var error: NSError? { NSUnimplemented() }
fileprivate var _error: NSError?
/*@NSCopying*/ open var error: NSError? {
return self._error
}

/// Suspend the task.
///
Expand Down Expand Up @@ -877,6 +880,8 @@ extension URLSessionTask {
}
}
func completeTask(withError error: NSError) {
self._error = error

guard case .transferFailed = internalState else {
fatalError("Trying to complete the task, but its transfer isn't complete / failed.")
}
Expand Down Expand Up @@ -1032,8 +1037,8 @@ fileprivate extension URLSessionTask {
guard case .waitingForResponseCompletionHandler(let ts) = internalState else { fatalError("Received response disposition, but we're not waiting for it.") }
switch disposition {
case .cancel:
//TODO: Fail the task with NSURLErrorCancelled
NSUnimplemented()
let error = NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled)
self.completeTask(withError: error)
case .allow:
// Continue the transfer. This will unpause the easy handle.
internalState = .transferInProgress(ts)
Expand Down
37 changes: 36 additions & 1 deletion TestFoundation/TestNSURLSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class TestURLSession : XCTestCase {
("test_downloadTaskWithURLRequest", test_downloadTaskWithURLRequest),
("test_downloadTaskWithRequestAndHandler", test_downloadTaskWithRequestAndHandler),
("test_downloadTaskWithURLAndHandler", test_downloadTaskWithURLAndHandler),
("test_finishTaskAndInvalidate", test_finishTasksAndInvalidate)
("test_finishTaskAndInvalidate", test_finishTasksAndInvalidate),
("test_taskError", test_taskError),
("test_taskCopy", test_taskCopy),
]
}

Expand Down Expand Up @@ -262,6 +264,39 @@ class TestURLSession : XCTestCase {
session.finishTasksAndInvalidate()
waitForExpectations(timeout: 12)
}

func test_taskError() {
let url = URL(string: "http://127.0.0.1:\(serverPort)/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
XCTAssertNotNil(error)
XCTAssertEqual(error?.code, NSURLErrorBadURL)
completionExpectation.fulfill()
}
//should result in Bad URL error
task.resume()

waitForExpectations(timeout: 5) { error in
XCTAssertNil(error)

XCTAssertNotNil(task.error)
XCTAssertEqual(task.error?.code, NSURLErrorBadURL)
}
}

func test_taskCopy() {
let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: nil)
let task = session.dataTask(with: url)

XCTAssert(task.isEqual(task.copy()))
}
}

class SessionDelegate: NSObject, URLSessionDelegate {
Expand Down