DownloadTests.swift 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. //
  2. // DownloadTests.swift
  3. //
  4. // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. import Alamofire
  25. import Foundation
  26. import XCTest
  27. final class DownloadInitializationTests: BaseTestCase {
  28. func testDownloadClassMethodWithMethodURLAndDestination() {
  29. // Given
  30. let endpoint = Endpoint.get
  31. let expectation = self.expectation(description: "download should complete")
  32. // When
  33. let request = AF.download(endpoint).response { _ in
  34. expectation.fulfill()
  35. }
  36. waitForExpectations(timeout: timeout)
  37. // Then
  38. XCTAssertNotNil(request.request)
  39. XCTAssertEqual(request.request?.httpMethod, "GET")
  40. XCTAssertEqual(request.request?.url, endpoint.url)
  41. XCTAssertNotNil(request.response)
  42. }
  43. func testDownloadClassMethodWithMethodURLHeadersAndDestination() {
  44. // Given
  45. let endpoint = Endpoint.get
  46. let headers: HTTPHeaders = ["Authorization": "123456"]
  47. let expectation = self.expectation(description: "download should complete")
  48. // When
  49. let request = AF.download(endpoint, headers: headers).response { _ in
  50. expectation.fulfill()
  51. }
  52. waitForExpectations(timeout: timeout)
  53. // Then
  54. XCTAssertNotNil(request.request)
  55. XCTAssertEqual(request.request?.httpMethod, "GET")
  56. XCTAssertEqual(request.request?.url, endpoint.url)
  57. XCTAssertEqual(request.request?.headers["Authorization"], "123456")
  58. XCTAssertNotNil(request.response)
  59. }
  60. }
  61. // MARK: -
  62. final class DownloadResponseTests: BaseTestCase {
  63. private var randomCachesFileURL: URL {
  64. testDirectoryURL.appendingPathComponent("\(UUID().uuidString).json")
  65. }
  66. func testDownloadRequest() {
  67. // Given
  68. let fileURL = randomCachesFileURL
  69. let numberOfLines = 10
  70. let endpoint = Endpoint.stream(numberOfLines)
  71. let destination: DownloadRequest.Destination = { _, _ in (fileURL, []) }
  72. let expectation = self.expectation(description: "Download request should download data to file: \(endpoint.url.absoluteString)")
  73. var response: DownloadResponse<URL?, AFError>?
  74. // When
  75. AF.download(endpoint, to: destination)
  76. .response { resp in
  77. response = resp
  78. expectation.fulfill()
  79. }
  80. waitForExpectations(timeout: timeout)
  81. // Then
  82. XCTAssertNotNil(response?.request)
  83. XCTAssertNotNil(response?.response)
  84. XCTAssertNotNil(response?.fileURL)
  85. XCTAssertNil(response?.resumeData)
  86. XCTAssertNil(response?.error)
  87. if let destinationURL = response?.fileURL {
  88. XCTAssertTrue(FileManager.default.fileExists(atPath: destinationURL.path))
  89. if let data = try? Data(contentsOf: destinationURL) {
  90. XCTAssertGreaterThan(data.count, 0)
  91. } else {
  92. XCTFail("data should exist for contents of destinationURL")
  93. }
  94. }
  95. }
  96. func testDownloadRequestResponseURLProducesURL() throws {
  97. // Given
  98. let expectation = self.expectation(description: "Download request should download data")
  99. var response: DownloadResponse<URL, AFError>?
  100. // When
  101. AF.download(.get)
  102. .responseURL { resp in
  103. response = resp
  104. expectation.fulfill()
  105. }
  106. waitForExpectations(timeout: timeout, handler: nil)
  107. // Then
  108. XCTAssertNotNil(response?.request)
  109. XCTAssertNotNil(response?.response)
  110. XCTAssertNotNil(response?.fileURL)
  111. XCTAssertNil(response?.resumeData)
  112. XCTAssertNil(response?.error)
  113. let url = try XCTUnwrap(response?.value)
  114. XCTAssertTrue(FileManager.default.fileExists(atPath: url.path))
  115. }
  116. func testCancelledDownloadRequest() {
  117. // Given
  118. let fileURL = randomCachesFileURL
  119. let numberOfLines = 10
  120. let destination: DownloadRequest.Destination = { _, _ in (fileURL, []) }
  121. let expectation = self.expectation(description: "Cancelled download request should not download data to file")
  122. var response: DownloadResponse<URL?, AFError>?
  123. // When
  124. AF.download(.stream(numberOfLines), to: destination)
  125. .response { resp in
  126. response = resp
  127. expectation.fulfill()
  128. }
  129. .cancel()
  130. waitForExpectations(timeout: timeout)
  131. // Then
  132. XCTAssertNil(response?.response)
  133. XCTAssertNil(response?.fileURL)
  134. XCTAssertNotNil(response?.error)
  135. XCTAssertEqual(response?.error?.isExplicitlyCancelledError, true)
  136. }
  137. func testDownloadRequestWithProgress() {
  138. // Given
  139. let randomBytes = 1 * 25 * 1024
  140. let endpoint = Endpoint.bytes(randomBytes)
  141. let expectation = self.expectation(description: "Bytes download progress should be reported: \(endpoint.url)")
  142. var progressValues: [Double] = []
  143. var response: DownloadResponse<URL?, AFError>?
  144. // When
  145. AF.download(endpoint)
  146. .downloadProgress { progress in
  147. progressValues.append(progress.fractionCompleted)
  148. }
  149. .response { resp in
  150. response = resp
  151. expectation.fulfill()
  152. }
  153. waitForExpectations(timeout: timeout)
  154. // Then
  155. XCTAssertNotNil(response?.request)
  156. XCTAssertNotNil(response?.response)
  157. XCTAssertNotNil(response?.fileURL)
  158. XCTAssertNil(response?.resumeData)
  159. XCTAssertNil(response?.error)
  160. var previousProgress: Double = progressValues.first ?? 0.0
  161. for progress in progressValues {
  162. XCTAssertGreaterThanOrEqual(progress, previousProgress)
  163. previousProgress = progress
  164. }
  165. if let lastProgressValue = progressValues.last {
  166. XCTAssertEqual(lastProgressValue, 1.0)
  167. } else {
  168. XCTFail("last item in progressValues should not be nil")
  169. }
  170. }
  171. func testDownloadRequestWithParameters() {
  172. // Given
  173. let fileURL = randomCachesFileURL
  174. let parameters = ["foo": "bar"]
  175. let destination: DownloadRequest.Destination = { _, _ in (fileURL, []) }
  176. let expectation = self.expectation(description: "Download request should download data to file")
  177. var response: DownloadResponse<URL?, AFError>?
  178. // When
  179. AF.download(Endpoint.get, parameters: parameters, to: destination)
  180. .response { resp in
  181. response = resp
  182. expectation.fulfill()
  183. }
  184. waitForExpectations(timeout: timeout)
  185. // Then
  186. XCTAssertNotNil(response?.request)
  187. XCTAssertNotNil(response?.response)
  188. XCTAssertNotNil(response?.fileURL)
  189. XCTAssertNil(response?.resumeData)
  190. XCTAssertNil(response?.error)
  191. if
  192. let data = try? Data(contentsOf: fileURL),
  193. let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
  194. let json = jsonObject as? [String: Any],
  195. let args = json["args"] as? [String: String] {
  196. XCTAssertEqual(args["foo"], "bar")
  197. } else {
  198. XCTFail("args parameter in JSON should not be nil")
  199. }
  200. }
  201. func testDownloadRequestWithHeaders() {
  202. // Given
  203. let fileURL = randomCachesFileURL
  204. let endpoint = Endpoint.get
  205. let headers: HTTPHeaders = ["Authorization": "123456"]
  206. let destination: DownloadRequest.Destination = { _, _ in (fileURL, []) }
  207. let expectation = self.expectation(description: "Download request should download data to file: \(endpoint.url)")
  208. var response: DownloadResponse<URL?, AFError>?
  209. // When
  210. AF.download(endpoint, headers: headers, to: destination)
  211. .response { resp in
  212. response = resp
  213. expectation.fulfill()
  214. }
  215. waitForExpectations(timeout: timeout)
  216. // Then
  217. XCTAssertNotNil(response?.request)
  218. XCTAssertNotNil(response?.response)
  219. XCTAssertNotNil(response?.fileURL)
  220. XCTAssertNil(response?.resumeData)
  221. XCTAssertNil(response?.error)
  222. if
  223. let data = try? Data(contentsOf: fileURL),
  224. let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
  225. let json = jsonObject as? [String: Any],
  226. let headers = json["headers"] as? [String: String] {
  227. XCTAssertEqual(headers["Authorization"], "123456")
  228. } else {
  229. XCTFail("headers parameter in JSON should not be nil")
  230. }
  231. }
  232. func testThatDownloadingFileAndMovingToDirectoryThatDoesNotExistThrowsError() {
  233. // Given
  234. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  235. let expectation = self.expectation(description: "Download request should download data but fail to move file")
  236. var response: DownloadResponse<URL?, AFError>?
  237. // When
  238. AF.download(.get, to: { _, _ in (fileURL, []) })
  239. .response { resp in
  240. response = resp
  241. expectation.fulfill()
  242. }
  243. waitForExpectations(timeout: timeout)
  244. // Then
  245. XCTAssertNotNil(response?.request)
  246. XCTAssertNotNil(response?.response)
  247. XCTAssertNil(response?.fileURL)
  248. XCTAssertNil(response?.resumeData)
  249. XCTAssertNotNil(response?.error)
  250. XCTAssertEqual((response?.error?.underlyingError as? CocoaError)?.code, .fileNoSuchFile)
  251. }
  252. func testThatDownloadOptionsCanCreateIntermediateDirectoriesPriorToMovingFile() {
  253. // Given
  254. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  255. let expectation = self.expectation(description: "Download request should download data to file: \(fileURL)")
  256. var response: DownloadResponse<URL?, AFError>?
  257. // When
  258. AF.download(.get, to: { _, _ in (fileURL, [.createIntermediateDirectories]) })
  259. .response { resp in
  260. response = resp
  261. expectation.fulfill()
  262. }
  263. waitForExpectations(timeout: timeout)
  264. // Then
  265. XCTAssertNotNil(response?.request)
  266. XCTAssertNotNil(response?.response)
  267. XCTAssertNotNil(response?.fileURL)
  268. XCTAssertNil(response?.resumeData)
  269. XCTAssertNil(response?.error)
  270. }
  271. func testThatDownloadingFileAndMovingToDestinationThatIsOccupiedThrowsError() throws {
  272. // Given
  273. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  274. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  275. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  276. try "random_data".write(to: fileURL, atomically: true, encoding: .utf8)
  277. let expectation = self.expectation(description: "Download should complete but fail to move file")
  278. var response: DownloadResponse<URL?, AFError>?
  279. // When
  280. AF.download(.get, to: { _, _ in (fileURL, []) })
  281. .response { resp in
  282. response = resp
  283. expectation.fulfill()
  284. }
  285. waitForExpectations(timeout: timeout)
  286. // Then
  287. XCTAssertTrue(directoryCreated)
  288. XCTAssertNotNil(response?.request)
  289. XCTAssertNotNil(response?.response)
  290. XCTAssertNil(response?.fileURL)
  291. XCTAssertNil(response?.resumeData)
  292. XCTAssertNotNil(response?.error)
  293. XCTAssertEqual((response?.error?.underlyingError as? CocoaError)?.code, .fileWriteFileExists)
  294. }
  295. func testThatDownloadOptionsCanRemovePreviousFilePriorToMovingFile() {
  296. // Given
  297. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  298. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  299. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  300. let expectation = self.expectation(description: "Download should complete and move file to URL: \(fileURL)")
  301. var response: DownloadResponse<URL?, AFError>?
  302. // When
  303. AF.download(.get,
  304. to: { _, _ in (fileURL, [.removePreviousFile, .createIntermediateDirectories]) })
  305. .response { resp in
  306. response = resp
  307. expectation.fulfill()
  308. }
  309. waitForExpectations(timeout: timeout)
  310. // Then
  311. XCTAssertTrue(directoryCreated)
  312. XCTAssertNotNil(response?.request)
  313. XCTAssertNotNil(response?.response)
  314. XCTAssertNotNil(response?.fileURL)
  315. XCTAssertNil(response?.resumeData)
  316. XCTAssertNil(response?.error)
  317. }
  318. }
  319. // MARK: -
  320. final class DownloadRequestEventsTestCase: BaseTestCase {
  321. func testThatDownloadRequestTriggersAllAppropriateLifetimeEvents() {
  322. // Given
  323. let eventMonitor = ClosureEventMonitor()
  324. let session = Session(eventMonitors: [eventMonitor])
  325. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  326. let didCreateInitialURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  327. let didCreateURLRequest = expectation(description: "didCreateURLRequest should fire")
  328. let didCreateTask = expectation(description: "didCreateTask should fire")
  329. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  330. let didComplete = expectation(description: "didComplete should fire")
  331. let didWriteData = expectation(description: "didWriteData should fire")
  332. let didFinishDownloading = expectation(description: "didFinishDownloading should fire")
  333. let didFinishWithResult = expectation(description: "didFinishWithResult should fire")
  334. let didCreate = expectation(description: "didCreate should fire")
  335. let didFinish = expectation(description: "didFinish should fire")
  336. let didResume = expectation(description: "didResume should fire")
  337. let didResumeTask = expectation(description: "didResumeTask should fire")
  338. let didParseResponse = expectation(description: "didParseResponse should fire")
  339. let responseHandler = expectation(description: "responseHandler should fire")
  340. var wroteData = false
  341. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  342. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateInitialURLRequest.fulfill() }
  343. eventMonitor.requestDidCreateURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  344. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  345. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  346. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  347. eventMonitor.downloadTaskDidWriteData = { _, _, _, _, _ in
  348. guard !wroteData else { return }
  349. wroteData = true
  350. didWriteData.fulfill()
  351. }
  352. eventMonitor.downloadTaskDidFinishDownloadingToURL = { _, _, _ in didFinishDownloading.fulfill() }
  353. eventMonitor.requestDidFinishDownloadingUsingTaskWithResult = { _, _, _ in didFinishWithResult.fulfill() }
  354. eventMonitor.requestDidCreateDestinationURL = { _, _ in didCreate.fulfill() }
  355. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  356. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  357. eventMonitor.requestDidResumeTask = { _, _ in didResumeTask.fulfill() }
  358. eventMonitor.requestDidParseDownloadResponse = { _, _ in didParseResponse.fulfill() }
  359. // When
  360. let request = session.download(.get).response { _ in
  361. responseHandler.fulfill()
  362. }
  363. waitForExpectations(timeout: timeout)
  364. // Then
  365. XCTAssertEqual(request.state, .finished)
  366. }
  367. func testThatCancelledDownloadRequestTriggersAllAppropriateLifetimeEvents() {
  368. // Given
  369. let eventMonitor = ClosureEventMonitor()
  370. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  371. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  372. let didCreateInitialURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  373. let didCreateURLRequest = expectation(description: "didCreateURLRequest should fire")
  374. let didCreateTask = expectation(description: "didCreateTask should fire")
  375. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  376. let didComplete = expectation(description: "didComplete should fire")
  377. let didFinish = expectation(description: "didFinish should fire")
  378. let didResume = expectation(description: "didResume should fire")
  379. let didResumeTask = expectation(description: "didResumeTask should fire")
  380. let didParseResponse = expectation(description: "didParseResponse should fire")
  381. let didCancel = expectation(description: "didCancel should fire")
  382. let didCancelTask = expectation(description: "didCancelTask should fire")
  383. let responseHandler = expectation(description: "responseHandler should fire")
  384. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  385. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateInitialURLRequest.fulfill() }
  386. eventMonitor.requestDidCreateURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  387. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  388. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  389. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  390. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  391. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  392. eventMonitor.requestDidParseDownloadResponse = { _, _ in didParseResponse.fulfill() }
  393. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  394. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  395. // When
  396. let request = session.download(.delay(5)).response { _ in
  397. responseHandler.fulfill()
  398. }
  399. eventMonitor.requestDidResumeTask = { [unowned request] _, _ in
  400. request.cancel()
  401. didResumeTask.fulfill()
  402. }
  403. request.resume()
  404. waitForExpectations(timeout: timeout)
  405. // Then
  406. XCTAssertEqual(request.state, .cancelled)
  407. }
  408. }
  409. // MARK: -
  410. final class DownloadResumeDataTestCase: BaseTestCase {
  411. func testThatCancelledDownloadRequestDoesNotProduceResumeData() {
  412. // Given
  413. let expectation = self.expectation(description: "Download should be cancelled")
  414. var cancelled = false
  415. var response: DownloadResponse<URL?, AFError>?
  416. // When
  417. let download = AF.download(.download())
  418. download.downloadProgress { [unowned download] progress in
  419. guard !cancelled else { return }
  420. if progress.fractionCompleted > 0.1 {
  421. download.cancel()
  422. cancelled = true
  423. }
  424. }
  425. download.response { resp in
  426. response = resp
  427. expectation.fulfill()
  428. }
  429. waitForExpectations(timeout: timeout)
  430. // Then
  431. XCTAssertNotNil(response?.request)
  432. XCTAssertNotNil(response?.response)
  433. XCTAssertNil(response?.fileURL)
  434. XCTAssertNotNil(response?.error)
  435. XCTAssertNil(response?.resumeData)
  436. XCTAssertNil(download.resumeData)
  437. }
  438. func testThatDownloadRequestProducesResumeDataOnError() {
  439. // Given
  440. let expectation = self.expectation(description: "download complete")
  441. var response: DownloadResponse<URL?, AFError>?
  442. // When
  443. let download = AF.download(.download(produceError: true))
  444. download.response { resp in
  445. response = resp
  446. expectation.fulfill()
  447. }
  448. waitForExpectations(timeout: timeout)
  449. // Then
  450. XCTAssertNotNil(response?.request)
  451. XCTAssertNotNil(response?.response)
  452. XCTAssertNil(response?.fileURL)
  453. XCTAssertNotNil(response?.error)
  454. XCTAssertNotNil(download.error?.downloadResumeData)
  455. XCTAssertNotNil(response?.resumeData)
  456. XCTAssertNotNil(download.resumeData)
  457. XCTAssertEqual(download.error?.downloadResumeData, response?.resumeData)
  458. XCTAssertEqual(response?.resumeData, download.resumeData)
  459. }
  460. func testThatCancelledDownloadResponseDataMatchesResumeData() {
  461. // Given
  462. let expectation = self.expectation(description: "Download should be cancelled")
  463. var cancelled = false
  464. var response: DownloadResponse<URL?, AFError>?
  465. // When
  466. let download = AF.download(.download())
  467. download.downloadProgress { [unowned download] progress in
  468. guard !cancelled else { return }
  469. if progress.fractionCompleted > 0.1 {
  470. download.cancel(producingResumeData: true)
  471. cancelled = true
  472. }
  473. }
  474. download.response { resp in
  475. response = resp
  476. expectation.fulfill()
  477. }
  478. waitForExpectations(timeout: timeout)
  479. // Then
  480. XCTAssertNotNil(response?.request)
  481. XCTAssertNotNil(response?.response)
  482. XCTAssertNil(response?.fileURL)
  483. XCTAssertNotNil(response?.error)
  484. XCTAssertNotNil(response?.resumeData)
  485. XCTAssertNotNil(download.resumeData)
  486. XCTAssertEqual(response?.resumeData, download.resumeData)
  487. }
  488. func testThatCancelledDownloadResumeDataIsAvailableWithJSONResponseSerializer() {
  489. // Given
  490. let expectation = self.expectation(description: "Download should be cancelled")
  491. var cancelled = false
  492. var response: DownloadResponse<Any, AFError>?
  493. // When
  494. let download = AF.download(.download())
  495. download.downloadProgress { [unowned download] progress in
  496. guard !cancelled else { return }
  497. if progress.fractionCompleted > 0.1 {
  498. download.cancel(producingResumeData: true)
  499. cancelled = true
  500. }
  501. }
  502. download.responseJSON { resp in
  503. response = resp
  504. expectation.fulfill()
  505. }
  506. waitForExpectations(timeout: timeout)
  507. // Then
  508. XCTAssertNotNil(response?.request)
  509. XCTAssertNotNil(response?.response)
  510. XCTAssertNil(response?.fileURL)
  511. XCTAssertEqual(response?.result.isFailure, true)
  512. XCTAssertNotNil(response?.result.failure)
  513. XCTAssertNotNil(response?.resumeData)
  514. XCTAssertNotNil(download.resumeData)
  515. XCTAssertEqual(response?.resumeData, download.resumeData)
  516. }
  517. func testThatCancelledDownloadCanBeResumedWithResumeData() {
  518. // Given
  519. let expectation1 = expectation(description: "Download should be cancelled")
  520. var cancelled = false
  521. var response1: DownloadResponse<Data, AFError>?
  522. // When
  523. let download = AF.download(.download())
  524. download.downloadProgress { [unowned download] progress in
  525. guard !cancelled else { return }
  526. if progress.fractionCompleted > 0.1 {
  527. download.cancel(producingResumeData: true)
  528. cancelled = true
  529. }
  530. }
  531. download.responseData { resp in
  532. response1 = resp
  533. expectation1.fulfill()
  534. }
  535. waitForExpectations(timeout: timeout)
  536. guard let resumeData = download.resumeData else {
  537. XCTFail("resumeData should not be nil")
  538. return
  539. }
  540. let expectation2 = expectation(description: "Download should complete")
  541. var progressValues: [Double] = []
  542. var response2: DownloadResponse<Data, AFError>?
  543. AF.download(resumingWith: resumeData)
  544. .downloadProgress { progress in
  545. progressValues.append(progress.fractionCompleted)
  546. }
  547. .responseData { resp in
  548. response2 = resp
  549. expectation2.fulfill()
  550. }
  551. waitForExpectations(timeout: timeout)
  552. // Then
  553. XCTAssertNotNil(response1?.request)
  554. XCTAssertNotNil(response1?.response)
  555. XCTAssertNil(response1?.fileURL)
  556. XCTAssertEqual(response1?.result.isFailure, true)
  557. XCTAssertNotNil(response1?.result.failure)
  558. XCTAssertNotNil(response2?.response)
  559. XCTAssertNotNil(response2?.fileURL)
  560. XCTAssertEqual(response2?.result.isSuccess, true)
  561. XCTAssertNil(response2?.result.failure)
  562. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.1) }
  563. }
  564. func testThatCancelledDownloadProducesMatchingResumeData() {
  565. // Given
  566. let expectation = self.expectation(description: "Download should be cancelled")
  567. var cancelled = false
  568. var receivedResumeData: Data?
  569. var response: DownloadResponse<URL?, AFError>?
  570. // When
  571. let download = AF.download(.download())
  572. download.downloadProgress { [unowned download] progress in
  573. guard !cancelled else { return }
  574. if progress.fractionCompleted > 0.1 {
  575. download.cancel { receivedResumeData = $0 }
  576. cancelled = true
  577. }
  578. }
  579. download.response { resp in
  580. response = resp
  581. expectation.fulfill()
  582. }
  583. waitForExpectations(timeout: timeout)
  584. // Then
  585. XCTAssertNotNil(response?.request)
  586. XCTAssertNotNil(response?.response)
  587. XCTAssertNil(response?.fileURL)
  588. XCTAssertNotNil(response?.error)
  589. XCTAssertNotNil(response?.resumeData)
  590. XCTAssertNotNil(download.resumeData)
  591. XCTAssertEqual(response?.resumeData, download.resumeData)
  592. XCTAssertEqual(response?.resumeData, receivedResumeData)
  593. XCTAssertEqual(download.resumeData, receivedResumeData)
  594. }
  595. }
  596. // MARK: -
  597. final class DownloadResponseMapTestCase: BaseTestCase {
  598. func testThatMapTransformsSuccessValue() {
  599. // Given
  600. let expectation = self.expectation(description: "request should succeed")
  601. var response: DownloadResponse<String, AFError>?
  602. // When
  603. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  604. response = resp.map { json in
  605. // json["args"]["foo"] is "bar": use this invariant to test the map function
  606. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  607. }
  608. expectation.fulfill()
  609. }
  610. waitForExpectations(timeout: timeout)
  611. // Then
  612. XCTAssertNotNil(response?.request)
  613. XCTAssertNotNil(response?.response)
  614. XCTAssertNotNil(response?.fileURL)
  615. XCTAssertNil(response?.resumeData)
  616. XCTAssertNil(response?.error)
  617. XCTAssertEqual(response?.result.success, "bar")
  618. XCTAssertNotNil(response?.metrics)
  619. }
  620. func testThatMapPreservesFailureError() {
  621. // Given
  622. let urlString = String.nonexistentDomain
  623. let expectation = self.expectation(description: "request should fail with 404")
  624. var response: DownloadResponse<String, AFError>?
  625. // When
  626. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  627. response = resp.map { _ in "ignored" }
  628. expectation.fulfill()
  629. }
  630. waitForExpectations(timeout: timeout)
  631. // Then
  632. XCTAssertNotNil(response?.request)
  633. XCTAssertNil(response?.response)
  634. XCTAssertNil(response?.fileURL)
  635. XCTAssertNil(response?.resumeData)
  636. XCTAssertNotNil(response?.error)
  637. XCTAssertEqual(response?.result.isFailure, true)
  638. XCTAssertNotNil(response?.metrics)
  639. }
  640. }
  641. // MARK: -
  642. final class DownloadResponseTryMapTestCase: BaseTestCase {
  643. func testThatTryMapTransformsSuccessValue() {
  644. // Given
  645. let expectation = self.expectation(description: "request should succeed")
  646. var response: DownloadResponse<String, Error>?
  647. // When
  648. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  649. response = resp.tryMap { json in
  650. // json["args"]["foo"] is "bar": use this invariant to test the map function
  651. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  652. }
  653. expectation.fulfill()
  654. }
  655. waitForExpectations(timeout: timeout)
  656. // Then
  657. XCTAssertNotNil(response?.request)
  658. XCTAssertNotNil(response?.response)
  659. XCTAssertNotNil(response?.fileURL)
  660. XCTAssertNil(response?.resumeData)
  661. XCTAssertNil(response?.error)
  662. XCTAssertEqual(response?.result.success, "bar")
  663. XCTAssertNotNil(response?.metrics)
  664. }
  665. func testThatTryMapCatchesTransformationError() {
  666. // Given
  667. struct TransformError: Error {}
  668. let expectation = self.expectation(description: "request should succeed")
  669. var response: DownloadResponse<String, Error>?
  670. // When
  671. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  672. response = resp.tryMap { _ in
  673. throw TransformError()
  674. }
  675. expectation.fulfill()
  676. }
  677. waitForExpectations(timeout: timeout)
  678. // Then
  679. XCTAssertNotNil(response?.request)
  680. XCTAssertNotNil(response?.response)
  681. XCTAssertNotNil(response?.fileURL)
  682. XCTAssertNil(response?.resumeData)
  683. if let error = response?.result.failure {
  684. XCTAssertTrue(error is TransformError)
  685. } else {
  686. XCTFail("flatMap should catch the transformation error")
  687. }
  688. XCTAssertNotNil(response?.metrics)
  689. }
  690. func testThatTryMapPreservesFailureError() {
  691. // Given
  692. let urlString = String.nonexistentDomain
  693. let expectation = self.expectation(description: "request should fail with 404")
  694. var response: DownloadResponse<String, Error>?
  695. // When
  696. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  697. response = resp.tryMap { _ in "ignored" }
  698. expectation.fulfill()
  699. }
  700. waitForExpectations(timeout: timeout)
  701. // Then
  702. XCTAssertNotNil(response?.request)
  703. XCTAssertNil(response?.response)
  704. XCTAssertNil(response?.fileURL)
  705. XCTAssertNil(response?.resumeData)
  706. XCTAssertNotNil(response?.error)
  707. XCTAssertEqual(response?.result.isFailure, true)
  708. XCTAssertNotNil(response?.metrics)
  709. }
  710. }
  711. final class DownloadResponseMapErrorTestCase: BaseTestCase {
  712. func testThatMapErrorTransformsFailureValue() {
  713. // Given
  714. let urlString = String.nonexistentDomain
  715. let expectation = self.expectation(description: "request should not succeed")
  716. var response: DownloadResponse<Any, TestError>?
  717. // When
  718. AF.download(urlString).responseJSON { resp in
  719. response = resp.mapError { error in
  720. TestError.error(error: error)
  721. }
  722. expectation.fulfill()
  723. }
  724. waitForExpectations(timeout: timeout)
  725. // Then
  726. XCTAssertNotNil(response?.request)
  727. XCTAssertNil(response?.response)
  728. XCTAssertNil(response?.fileURL)
  729. XCTAssertNil(response?.resumeData)
  730. XCTAssertNotNil(response?.error)
  731. XCTAssertEqual(response?.result.isFailure, true)
  732. guard let error = response?.error, case .error = error else { XCTFail(); return }
  733. XCTAssertNotNil(response?.metrics)
  734. }
  735. func testThatMapErrorPreservesSuccessValue() {
  736. // Given
  737. let expectation = self.expectation(description: "request should succeed")
  738. var response: DownloadResponse<Data, TestError>?
  739. // When
  740. AF.download(.get).responseData { resp in
  741. response = resp.mapError { TestError.error(error: $0) }
  742. expectation.fulfill()
  743. }
  744. waitForExpectations(timeout: timeout)
  745. // Then
  746. XCTAssertNotNil(response?.request)
  747. XCTAssertNotNil(response?.response)
  748. XCTAssertNotNil(response?.fileURL)
  749. XCTAssertNil(response?.resumeData)
  750. XCTAssertEqual(response?.result.isSuccess, true)
  751. XCTAssertNotNil(response?.metrics)
  752. }
  753. }
  754. // MARK: -
  755. final class DownloadResponseTryMapErrorTestCase: BaseTestCase {
  756. func testThatTryMapErrorPreservesSuccessValue() {
  757. // Given
  758. let expectation = self.expectation(description: "request should succeed")
  759. var response: DownloadResponse<Data, Error>?
  760. // When
  761. AF.download(.get).responseData { resp in
  762. response = resp.tryMapError { TestError.error(error: $0) }
  763. expectation.fulfill()
  764. }
  765. waitForExpectations(timeout: timeout)
  766. // Then
  767. XCTAssertNotNil(response?.request)
  768. XCTAssertNotNil(response?.response)
  769. XCTAssertNotNil(response?.fileURL)
  770. XCTAssertNil(response?.resumeData)
  771. XCTAssertNil(response?.error)
  772. XCTAssertEqual(response?.result.isSuccess, true)
  773. XCTAssertNotNil(response?.metrics)
  774. }
  775. func testThatTryMapErrorCatchesTransformationError() {
  776. // Given
  777. let urlString = String.nonexistentDomain
  778. let expectation = self.expectation(description: "request should fail")
  779. var response: DownloadResponse<Data, Error>?
  780. // When
  781. AF.download(urlString).responseData { resp in
  782. response = resp.tryMapError { _ in try TransformationError.error.alwaysFails() }
  783. expectation.fulfill()
  784. }
  785. waitForExpectations(timeout: timeout)
  786. // Then
  787. XCTAssertNotNil(response?.request)
  788. XCTAssertNil(response?.response)
  789. XCTAssertNil(response?.fileURL)
  790. XCTAssertNil(response?.resumeData)
  791. XCTAssertNotNil(response?.error)
  792. XCTAssertEqual(response?.result.isFailure, true)
  793. if let error = response?.result.failure {
  794. XCTAssertTrue(error is TransformationError)
  795. } else {
  796. XCTFail("flatMapError should catch the transformation error")
  797. }
  798. XCTAssertNotNil(response?.metrics)
  799. }
  800. func testThatTryMapErrorTransformsError() {
  801. // Given
  802. let urlString = String.nonexistentDomain
  803. let expectation = self.expectation(description: "request should fail")
  804. var response: DownloadResponse<Data, Error>?
  805. // When
  806. AF.download(urlString).responseData { resp in
  807. response = resp.tryMapError { TestError.error(error: $0) }
  808. expectation.fulfill()
  809. }
  810. waitForExpectations(timeout: timeout)
  811. // Then
  812. XCTAssertNotNil(response?.request)
  813. XCTAssertNil(response?.response)
  814. XCTAssertNil(response?.fileURL)
  815. XCTAssertNil(response?.resumeData)
  816. XCTAssertNotNil(response?.error)
  817. XCTAssertEqual(response?.result.isFailure, true)
  818. guard let error = response?.error, case TestError.error = error else { XCTFail(); return }
  819. XCTAssertNotNil(response?.metrics)
  820. }
  821. }