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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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(response?.resumeData)
  455. XCTAssertNotNil(download.resumeData)
  456. #if !(os(Linux) || os(Windows))
  457. XCTAssertNotNil(download.error?.downloadResumeData)
  458. XCTAssertEqual(download.error?.downloadResumeData, response?.resumeData)
  459. #endif
  460. XCTAssertEqual(response?.resumeData, download.resumeData)
  461. }
  462. func testThatCancelledDownloadResponseDataMatchesResumeData() {
  463. // Given
  464. let expectation = expectation(description: "Download should be cancelled")
  465. var cancelled = false
  466. var response: DownloadResponse<URL?, AFError>?
  467. // When
  468. let download = AF.download(.download())
  469. download.downloadProgress { [unowned download] progress in
  470. guard !cancelled else { return }
  471. if progress.fractionCompleted > 0.1 {
  472. download.cancel(producingResumeData: true)
  473. cancelled = true
  474. }
  475. }
  476. download.response { resp in
  477. response = resp
  478. expectation.fulfill()
  479. }
  480. waitForExpectations(timeout: timeout)
  481. // Then
  482. XCTAssertNotNil(response?.request)
  483. XCTAssertNotNil(response?.response)
  484. XCTAssertNil(response?.fileURL)
  485. XCTAssertNotNil(response?.error)
  486. XCTAssertNotNil(response?.resumeData)
  487. XCTAssertNotNil(download.resumeData)
  488. XCTAssertEqual(response?.resumeData, download.resumeData)
  489. }
  490. func testThatCancelledDownloadResumeDataIsAvailableWithDecodableResponseSerializer() {
  491. // Given
  492. let expectation = expectation(description: "Download should be cancelled")
  493. var cancelled = false
  494. var response: DownloadResponse<TestResponse, AFError>?
  495. // When
  496. let download = AF.download(.download())
  497. download.downloadProgress { [unowned download] progress in
  498. guard !cancelled else { return }
  499. if progress.fractionCompleted > 0.1 {
  500. download.cancel(producingResumeData: true)
  501. cancelled = true
  502. }
  503. }
  504. download.responseDecodable(of: TestResponse.self) { resp in
  505. response = resp
  506. expectation.fulfill()
  507. }
  508. waitForExpectations(timeout: timeout)
  509. // Then
  510. XCTAssertNotNil(response?.request)
  511. XCTAssertNotNil(response?.response)
  512. XCTAssertNil(response?.fileURL)
  513. XCTAssertEqual(response?.result.isFailure, true)
  514. XCTAssertNotNil(response?.result.failure)
  515. XCTAssertNotNil(response?.resumeData)
  516. XCTAssertNotNil(download.resumeData)
  517. XCTAssertEqual(response?.resumeData, download.resumeData)
  518. }
  519. func testThatCancelledDownloadCanBeResumedWithResumeData() {
  520. // Given
  521. let expectation1 = expectation(description: "Download should be cancelled")
  522. var cancelled = false
  523. var response1: DownloadResponse<Data, AFError>?
  524. // When
  525. let download = AF.download(.download())
  526. download.downloadProgress { [unowned download] progress in
  527. guard !cancelled else { return }
  528. if progress.fractionCompleted > 0.1 {
  529. download.cancel(producingResumeData: true)
  530. cancelled = true
  531. }
  532. }
  533. download.responseData { resp in
  534. response1 = resp
  535. expectation1.fulfill()
  536. }
  537. waitForExpectations(timeout: timeout)
  538. guard let resumeData = download.resumeData else {
  539. XCTFail("resumeData should not be nil")
  540. return
  541. }
  542. let expectation2 = expectation(description: "Download should complete")
  543. var progressValues: [Double] = []
  544. var response2: DownloadResponse<Data, AFError>?
  545. AF.download(resumingWith: resumeData)
  546. .downloadProgress { progress in
  547. progressValues.append(progress.fractionCompleted)
  548. }
  549. .responseData { resp in
  550. response2 = resp
  551. expectation2.fulfill()
  552. }
  553. waitForExpectations(timeout: timeout)
  554. // Then
  555. XCTAssertNotNil(response1?.request)
  556. XCTAssertNotNil(response1?.response)
  557. XCTAssertNil(response1?.fileURL)
  558. XCTAssertEqual(response1?.result.isFailure, true)
  559. XCTAssertNotNil(response1?.result.failure)
  560. XCTAssertNotNil(response2?.response)
  561. XCTAssertNotNil(response2?.fileURL)
  562. XCTAssertEqual(response2?.result.isSuccess, true)
  563. XCTAssertNil(response2?.result.failure)
  564. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.1) }
  565. }
  566. func testThatCancelledDownloadProducesMatchingResumeData() {
  567. // Given
  568. let expectation = expectation(description: "Download should be cancelled")
  569. var cancelled = false
  570. var receivedResumeData: Data?
  571. var response: DownloadResponse<URL?, AFError>?
  572. // When
  573. let download = AF.download(.download())
  574. download.downloadProgress { [unowned download] progress in
  575. guard !cancelled else { return }
  576. if progress.fractionCompleted > 0.1 {
  577. download.cancel { receivedResumeData = $0 }
  578. cancelled = true
  579. }
  580. }
  581. download.response { resp in
  582. response = resp
  583. expectation.fulfill()
  584. }
  585. waitForExpectations(timeout: timeout)
  586. // Then
  587. XCTAssertNotNil(response?.request)
  588. XCTAssertNotNil(response?.response)
  589. XCTAssertNil(response?.fileURL)
  590. XCTAssertNotNil(response?.error)
  591. XCTAssertNotNil(response?.resumeData)
  592. XCTAssertNotNil(download.resumeData)
  593. XCTAssertEqual(response?.resumeData, download.resumeData)
  594. XCTAssertEqual(response?.resumeData, receivedResumeData)
  595. XCTAssertEqual(download.resumeData, receivedResumeData)
  596. }
  597. }
  598. // MARK: -
  599. final class DownloadResponseMapTestCase: BaseTestCase {
  600. func testThatMapTransformsSuccessValue() {
  601. // Given
  602. let expectation = expectation(description: "request should succeed")
  603. var response: DownloadResponse<String, AFError>?
  604. // When
  605. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  606. response = resp.map { response in
  607. response.args?["foo"] ?? "invalid"
  608. }
  609. expectation.fulfill()
  610. }
  611. waitForExpectations(timeout: timeout)
  612. // Then
  613. XCTAssertNotNil(response?.request)
  614. XCTAssertNotNil(response?.response)
  615. XCTAssertNotNil(response?.fileURL)
  616. XCTAssertNil(response?.resumeData)
  617. XCTAssertNil(response?.error)
  618. XCTAssertEqual(response?.result.success, "bar")
  619. XCTAssertNotNil(response?.metrics)
  620. }
  621. func testThatMapPreservesFailureError() {
  622. // Given
  623. let urlString = String.invalidURL
  624. let expectation = expectation(description: "request should fail with invalid URL")
  625. var response: DownloadResponse<String, AFError>?
  626. // When
  627. AF.download(urlString, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  628. response = resp.map { _ in "ignored" }
  629. expectation.fulfill()
  630. }
  631. waitForExpectations(timeout: timeout)
  632. // Then
  633. XCTAssertNotNil(response?.request)
  634. XCTAssertNil(response?.response)
  635. XCTAssertNil(response?.fileURL)
  636. XCTAssertNil(response?.resumeData)
  637. XCTAssertNotNil(response?.error)
  638. XCTAssertEqual(response?.result.isFailure, true)
  639. XCTAssertNotNil(response?.metrics)
  640. }
  641. }
  642. // MARK: -
  643. final class DownloadResponseTryMapTestCase: BaseTestCase {
  644. func testThatTryMapTransformsSuccessValue() {
  645. // Given
  646. let expectation = expectation(description: "request should succeed")
  647. var response: DownloadResponse<String, Error>?
  648. // When
  649. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  650. response = resp.tryMap { response in
  651. response.args?["foo"] ?? "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 = expectation(description: "request should succeed")
  669. var response: DownloadResponse<String, Error>?
  670. // When
  671. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { 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.invalidURL
  693. let expectation = expectation(description: "request should fail with 404")
  694. var response: DownloadResponse<String, Error>?
  695. // When
  696. AF.download(urlString, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { 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.invalidURL
  715. let expectation = expectation(description: "request should not succeed")
  716. var response: DownloadResponse<TestResponse, TestError>?
  717. // When
  718. AF.download(urlString).responseDecodable(of: TestResponse.self) { 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 = 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 = 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.invalidURL
  778. let expectation = 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.invalidURL
  803. let expectation = 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. }