DownloadTests.swift 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  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. let endpoint = Endpoint.largeImage
  412. func testThatCancelledDownloadRequestDoesNotProduceResumeData() {
  413. // Given
  414. let expectation = self.expectation(description: "Download should be cancelled")
  415. var cancelled = false
  416. var response: DownloadResponse<URL?, AFError>?
  417. // When
  418. let download = AF.download(endpoint)
  419. download.downloadProgress { [unowned download] progress in
  420. NSLog("%@", progress)
  421. guard !cancelled else { return }
  422. if progress.fractionCompleted > 0.1 {
  423. download.cancel()
  424. cancelled = true
  425. }
  426. }
  427. download.response { resp in
  428. response = resp
  429. expectation.fulfill()
  430. }
  431. waitForExpectations(timeout: 10)
  432. // Then
  433. XCTAssertNotNil(response?.request)
  434. XCTAssertNotNil(response?.response)
  435. XCTAssertNil(response?.fileURL)
  436. XCTAssertNotNil(response?.error)
  437. XCTAssertNil(response?.resumeData)
  438. XCTAssertNil(download.resumeData)
  439. }
  440. func testThatCancelledDownloadResponseDataMatchesResumeData() {
  441. // Given
  442. let expectation = self.expectation(description: "Download should be cancelled")
  443. var cancelled = false
  444. var response: DownloadResponse<URL?, AFError>?
  445. // When
  446. let download = AF.download(endpoint)
  447. download.downloadProgress { [unowned download] progress in
  448. guard !cancelled else { return }
  449. if progress.fractionCompleted > 0.1 {
  450. download.cancel(producingResumeData: true)
  451. cancelled = true
  452. }
  453. }
  454. download.response { resp in
  455. response = resp
  456. expectation.fulfill()
  457. }
  458. waitForExpectations(timeout: timeout)
  459. // Then
  460. XCTAssertNotNil(response?.request)
  461. XCTAssertNotNil(response?.response)
  462. XCTAssertNil(response?.fileURL)
  463. XCTAssertNotNil(response?.error)
  464. XCTAssertNotNil(response?.resumeData)
  465. XCTAssertNotNil(download.resumeData)
  466. XCTAssertEqual(response?.resumeData, download.resumeData)
  467. }
  468. func testThatCancelledDownloadResumeDataIsAvailableWithJSONResponseSerializer() {
  469. // Given
  470. let expectation = self.expectation(description: "Download should be cancelled")
  471. var cancelled = false
  472. var response: DownloadResponse<Any, AFError>?
  473. // When
  474. let download = AF.download(endpoint)
  475. download.downloadProgress { [unowned download] progress in
  476. guard !cancelled else { return }
  477. if progress.fractionCompleted > 0.1 {
  478. download.cancel(producingResumeData: true)
  479. cancelled = true
  480. }
  481. }
  482. download.responseJSON { resp in
  483. response = resp
  484. expectation.fulfill()
  485. }
  486. waitForExpectations(timeout: timeout)
  487. // Then
  488. XCTAssertNotNil(response?.request)
  489. XCTAssertNotNil(response?.response)
  490. XCTAssertNil(response?.fileURL)
  491. XCTAssertEqual(response?.result.isFailure, true)
  492. XCTAssertNotNil(response?.result.failure)
  493. XCTAssertNotNil(response?.resumeData)
  494. XCTAssertNotNil(download.resumeData)
  495. XCTAssertEqual(response?.resumeData, download.resumeData)
  496. }
  497. // Disabled until we can find another source which supports resume ranges.
  498. func _testThatCancelledDownloadCanBeResumedWithResumeData() {
  499. // Given
  500. let expectation1 = expectation(description: "Download should be cancelled")
  501. var cancelled = false
  502. var response1: DownloadResponse<Data, AFError>?
  503. // When
  504. let download = AF.download(endpoint)
  505. download.downloadProgress { [unowned download] progress in
  506. guard !cancelled else { return }
  507. if progress.fractionCompleted > 0.1 {
  508. download.cancel(producingResumeData: true)
  509. cancelled = true
  510. }
  511. }
  512. download.responseData { resp in
  513. response1 = resp
  514. expectation1.fulfill()
  515. }
  516. waitForExpectations(timeout: timeout)
  517. guard let resumeData = download.resumeData else {
  518. XCTFail("resumeData should not be nil")
  519. return
  520. }
  521. let expectation2 = expectation(description: "Download should complete")
  522. var progressValues: [Double] = []
  523. var response2: DownloadResponse<Data, AFError>?
  524. AF.download(resumingWith: resumeData)
  525. .downloadProgress { progress in
  526. progressValues.append(progress.fractionCompleted)
  527. }
  528. .responseData { resp in
  529. response2 = resp
  530. expectation2.fulfill()
  531. }
  532. waitForExpectations(timeout: timeout)
  533. // Then
  534. XCTAssertNotNil(response1?.request)
  535. XCTAssertNotNil(response1?.response)
  536. XCTAssertNil(response1?.fileURL)
  537. XCTAssertEqual(response1?.result.isFailure, true)
  538. XCTAssertNotNil(response1?.result.failure)
  539. XCTAssertNotNil(response2?.response)
  540. XCTAssertNotNil(response2?.fileURL)
  541. XCTAssertEqual(response2?.result.isSuccess, true)
  542. XCTAssertNil(response2?.result.failure)
  543. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.1) }
  544. }
  545. func testThatCancelledDownloadProducesMatchingResumeData() {
  546. // Given
  547. let expectation = self.expectation(description: "Download should be cancelled")
  548. var cancelled = false
  549. var receivedResumeData: Data?
  550. var response: DownloadResponse<URL?, AFError>?
  551. // When
  552. let download = AF.download(endpoint)
  553. download.downloadProgress { [unowned download] progress in
  554. guard !cancelled else { return }
  555. if progress.fractionCompleted > 0.1 {
  556. download.cancel { receivedResumeData = $0 }
  557. cancelled = true
  558. }
  559. }
  560. download.response { resp in
  561. response = resp
  562. expectation.fulfill()
  563. }
  564. waitForExpectations(timeout: timeout)
  565. // Then
  566. XCTAssertNotNil(response?.request)
  567. XCTAssertNotNil(response?.response)
  568. XCTAssertNil(response?.fileURL)
  569. XCTAssertNotNil(response?.error)
  570. XCTAssertNotNil(response?.resumeData)
  571. XCTAssertNotNil(download.resumeData)
  572. XCTAssertEqual(response?.resumeData, download.resumeData)
  573. XCTAssertEqual(response?.resumeData, receivedResumeData)
  574. XCTAssertEqual(download.resumeData, receivedResumeData)
  575. }
  576. }
  577. // MARK: -
  578. final class DownloadResponseMapTestCase: BaseTestCase {
  579. func testThatMapTransformsSuccessValue() {
  580. // Given
  581. let expectation = self.expectation(description: "request should succeed")
  582. var response: DownloadResponse<String, AFError>?
  583. // When
  584. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  585. response = resp.map { json in
  586. // json["args"]["foo"] is "bar": use this invariant to test the map function
  587. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  588. }
  589. expectation.fulfill()
  590. }
  591. waitForExpectations(timeout: timeout)
  592. // Then
  593. XCTAssertNotNil(response?.request)
  594. XCTAssertNotNil(response?.response)
  595. XCTAssertNotNil(response?.fileURL)
  596. XCTAssertNil(response?.resumeData)
  597. XCTAssertNil(response?.error)
  598. XCTAssertEqual(response?.result.success, "bar")
  599. XCTAssertNotNil(response?.metrics)
  600. }
  601. func testThatMapPreservesFailureError() {
  602. // Given
  603. let urlString = String.nonexistentDomain
  604. let expectation = self.expectation(description: "request should fail with 404")
  605. var response: DownloadResponse<String, AFError>?
  606. // When
  607. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  608. response = resp.map { _ in "ignored" }
  609. expectation.fulfill()
  610. }
  611. waitForExpectations(timeout: timeout)
  612. // Then
  613. XCTAssertNotNil(response?.request)
  614. XCTAssertNil(response?.response)
  615. XCTAssertNil(response?.fileURL)
  616. XCTAssertNil(response?.resumeData)
  617. XCTAssertNotNil(response?.error)
  618. XCTAssertEqual(response?.result.isFailure, true)
  619. XCTAssertNotNil(response?.metrics)
  620. }
  621. }
  622. // MARK: -
  623. final class DownloadResponseTryMapTestCase: BaseTestCase {
  624. func testThatTryMapTransformsSuccessValue() {
  625. // Given
  626. let expectation = self.expectation(description: "request should succeed")
  627. var response: DownloadResponse<String, Error>?
  628. // When
  629. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  630. response = resp.tryMap { json in
  631. // json["args"]["foo"] is "bar": use this invariant to test the map function
  632. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  633. }
  634. expectation.fulfill()
  635. }
  636. waitForExpectations(timeout: timeout)
  637. // Then
  638. XCTAssertNotNil(response?.request)
  639. XCTAssertNotNil(response?.response)
  640. XCTAssertNotNil(response?.fileURL)
  641. XCTAssertNil(response?.resumeData)
  642. XCTAssertNil(response?.error)
  643. XCTAssertEqual(response?.result.success, "bar")
  644. XCTAssertNotNil(response?.metrics)
  645. }
  646. func testThatTryMapCatchesTransformationError() {
  647. // Given
  648. struct TransformError: Error {}
  649. let expectation = self.expectation(description: "request should succeed")
  650. var response: DownloadResponse<String, Error>?
  651. // When
  652. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  653. response = resp.tryMap { _ in
  654. throw TransformError()
  655. }
  656. expectation.fulfill()
  657. }
  658. waitForExpectations(timeout: timeout)
  659. // Then
  660. XCTAssertNotNil(response?.request)
  661. XCTAssertNotNil(response?.response)
  662. XCTAssertNotNil(response?.fileURL)
  663. XCTAssertNil(response?.resumeData)
  664. if let error = response?.result.failure {
  665. XCTAssertTrue(error is TransformError)
  666. } else {
  667. XCTFail("flatMap should catch the transformation error")
  668. }
  669. XCTAssertNotNil(response?.metrics)
  670. }
  671. func testThatTryMapPreservesFailureError() {
  672. // Given
  673. let urlString = String.nonexistentDomain
  674. let expectation = self.expectation(description: "request should fail with 404")
  675. var response: DownloadResponse<String, Error>?
  676. // When
  677. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  678. response = resp.tryMap { _ in "ignored" }
  679. expectation.fulfill()
  680. }
  681. waitForExpectations(timeout: timeout)
  682. // Then
  683. XCTAssertNotNil(response?.request)
  684. XCTAssertNil(response?.response)
  685. XCTAssertNil(response?.fileURL)
  686. XCTAssertNil(response?.resumeData)
  687. XCTAssertNotNil(response?.error)
  688. XCTAssertEqual(response?.result.isFailure, true)
  689. XCTAssertNotNil(response?.metrics)
  690. }
  691. }
  692. final class DownloadResponseMapErrorTestCase: BaseTestCase {
  693. func testThatMapErrorTransformsFailureValue() {
  694. // Given
  695. let urlString = String.nonexistentDomain
  696. let expectation = self.expectation(description: "request should not succeed")
  697. var response: DownloadResponse<Any, TestError>?
  698. // When
  699. AF.download(urlString).responseJSON { resp in
  700. response = resp.mapError { error in
  701. TestError.error(error: error)
  702. }
  703. expectation.fulfill()
  704. }
  705. waitForExpectations(timeout: timeout)
  706. // Then
  707. XCTAssertNotNil(response?.request)
  708. XCTAssertNil(response?.response)
  709. XCTAssertNil(response?.fileURL)
  710. XCTAssertNil(response?.resumeData)
  711. XCTAssertNotNil(response?.error)
  712. XCTAssertEqual(response?.result.isFailure, true)
  713. guard let error = response?.error, case .error = error else { XCTFail(); return }
  714. XCTAssertNotNil(response?.metrics)
  715. }
  716. func testThatMapErrorPreservesSuccessValue() {
  717. // Given
  718. let expectation = self.expectation(description: "request should succeed")
  719. var response: DownloadResponse<Data, TestError>?
  720. // When
  721. AF.download(.get).responseData { resp in
  722. response = resp.mapError { TestError.error(error: $0) }
  723. expectation.fulfill()
  724. }
  725. waitForExpectations(timeout: timeout)
  726. // Then
  727. XCTAssertNotNil(response?.request)
  728. XCTAssertNotNil(response?.response)
  729. XCTAssertNotNil(response?.fileURL)
  730. XCTAssertNil(response?.resumeData)
  731. XCTAssertEqual(response?.result.isSuccess, true)
  732. XCTAssertNotNil(response?.metrics)
  733. }
  734. }
  735. // MARK: -
  736. final class DownloadResponseTryMapErrorTestCase: BaseTestCase {
  737. func testThatTryMapErrorPreservesSuccessValue() {
  738. // Given
  739. let expectation = self.expectation(description: "request should succeed")
  740. var response: DownloadResponse<Data, Error>?
  741. // When
  742. AF.download(.get).responseData { resp in
  743. response = resp.tryMapError { TestError.error(error: $0) }
  744. expectation.fulfill()
  745. }
  746. waitForExpectations(timeout: timeout)
  747. // Then
  748. XCTAssertNotNil(response?.request)
  749. XCTAssertNotNil(response?.response)
  750. XCTAssertNotNil(response?.fileURL)
  751. XCTAssertNil(response?.resumeData)
  752. XCTAssertNil(response?.error)
  753. XCTAssertEqual(response?.result.isSuccess, true)
  754. XCTAssertNotNil(response?.metrics)
  755. }
  756. func testThatTryMapErrorCatchesTransformationError() {
  757. // Given
  758. let urlString = String.nonexistentDomain
  759. let expectation = self.expectation(description: "request should fail")
  760. var response: DownloadResponse<Data, Error>?
  761. // When
  762. AF.download(urlString).responseData { resp in
  763. response = resp.tryMapError { _ in try TransformationError.error.alwaysFails() }
  764. expectation.fulfill()
  765. }
  766. waitForExpectations(timeout: timeout)
  767. // Then
  768. XCTAssertNotNil(response?.request)
  769. XCTAssertNil(response?.response)
  770. XCTAssertNil(response?.fileURL)
  771. XCTAssertNil(response?.resumeData)
  772. XCTAssertNotNil(response?.error)
  773. XCTAssertEqual(response?.result.isFailure, true)
  774. if let error = response?.result.failure {
  775. XCTAssertTrue(error is TransformationError)
  776. } else {
  777. XCTFail("flatMapError should catch the transformation error")
  778. }
  779. XCTAssertNotNil(response?.metrics)
  780. }
  781. func testThatTryMapErrorTransformsError() {
  782. // Given
  783. let urlString = String.nonexistentDomain
  784. let expectation = self.expectation(description: "request should fail")
  785. var response: DownloadResponse<Data, Error>?
  786. // When
  787. AF.download(urlString).responseData { resp in
  788. response = resp.tryMapError { TestError.error(error: $0) }
  789. expectation.fulfill()
  790. }
  791. waitForExpectations(timeout: timeout)
  792. // Then
  793. XCTAssertNotNil(response?.request)
  794. XCTAssertNil(response?.response)
  795. XCTAssertNil(response?.fileURL)
  796. XCTAssertNil(response?.resumeData)
  797. XCTAssertNotNil(response?.error)
  798. XCTAssertEqual(response?.result.isFailure, true)
  799. guard let error = response?.error, case TestError.error = error else { XCTFail(); return }
  800. XCTAssertNotNil(response?.metrics)
  801. }
  802. }