2
0

DownloadTests.swift 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027
  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(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 = self.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 testThatCancelledDownloadResumeDataIsAvailableWithJSONResponseSerializer() {
  491. // Given
  492. let expectation = self.expectation(description: "Download should be cancelled")
  493. var cancelled = false
  494. var response: DownloadResponse<Any, 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.responseJSON { 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 = self.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 = self.expectation(description: "request should succeed")
  603. var response: DownloadResponse<String, AFError>?
  604. // When
  605. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  606. response = resp.map { json in
  607. // json["args"]["foo"] is "bar": use this invariant to test the map function
  608. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  609. }
  610. expectation.fulfill()
  611. }
  612. waitForExpectations(timeout: timeout)
  613. // Then
  614. XCTAssertNotNil(response?.request)
  615. XCTAssertNotNil(response?.response)
  616. XCTAssertNotNil(response?.fileURL)
  617. XCTAssertNil(response?.resumeData)
  618. XCTAssertNil(response?.error)
  619. XCTAssertEqual(response?.result.success, "bar")
  620. XCTAssertNotNil(response?.metrics)
  621. }
  622. func testThatMapPreservesFailureError() {
  623. // Given
  624. let urlString = String.nonexistentDomain
  625. let expectation = self.expectation(description: "request should fail with 404")
  626. var response: DownloadResponse<String, AFError>?
  627. // When
  628. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  629. response = resp.map { _ in "ignored" }
  630. expectation.fulfill()
  631. }
  632. waitForExpectations(timeout: timeout)
  633. // Then
  634. XCTAssertNotNil(response?.request)
  635. XCTAssertNil(response?.response)
  636. XCTAssertNil(response?.fileURL)
  637. XCTAssertNil(response?.resumeData)
  638. XCTAssertNotNil(response?.error)
  639. XCTAssertEqual(response?.result.isFailure, true)
  640. XCTAssertNotNil(response?.metrics)
  641. }
  642. }
  643. // MARK: -
  644. final class DownloadResponseTryMapTestCase: BaseTestCase {
  645. func testThatTryMapTransformsSuccessValue() {
  646. // Given
  647. let expectation = self.expectation(description: "request should succeed")
  648. var response: DownloadResponse<String, Error>?
  649. // When
  650. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  651. response = resp.tryMap { json in
  652. // json["args"]["foo"] is "bar": use this invariant to test the map function
  653. ((json as? [String: Any])?["args"] as? [String: Any])?["foo"] as? String ?? "invalid"
  654. }
  655. expectation.fulfill()
  656. }
  657. waitForExpectations(timeout: timeout)
  658. // Then
  659. XCTAssertNotNil(response?.request)
  660. XCTAssertNotNil(response?.response)
  661. XCTAssertNotNil(response?.fileURL)
  662. XCTAssertNil(response?.resumeData)
  663. XCTAssertNil(response?.error)
  664. XCTAssertEqual(response?.result.success, "bar")
  665. XCTAssertNotNil(response?.metrics)
  666. }
  667. func testThatTryMapCatchesTransformationError() {
  668. // Given
  669. struct TransformError: Error {}
  670. let expectation = self.expectation(description: "request should succeed")
  671. var response: DownloadResponse<String, Error>?
  672. // When
  673. AF.download(.get, parameters: ["foo": "bar"]).responseJSON { resp in
  674. response = resp.tryMap { _ in
  675. throw TransformError()
  676. }
  677. expectation.fulfill()
  678. }
  679. waitForExpectations(timeout: timeout)
  680. // Then
  681. XCTAssertNotNil(response?.request)
  682. XCTAssertNotNil(response?.response)
  683. XCTAssertNotNil(response?.fileURL)
  684. XCTAssertNil(response?.resumeData)
  685. if let error = response?.result.failure {
  686. XCTAssertTrue(error is TransformError)
  687. } else {
  688. XCTFail("flatMap should catch the transformation error")
  689. }
  690. XCTAssertNotNil(response?.metrics)
  691. }
  692. func testThatTryMapPreservesFailureError() {
  693. // Given
  694. let urlString = String.nonexistentDomain
  695. let expectation = self.expectation(description: "request should fail with 404")
  696. var response: DownloadResponse<String, Error>?
  697. // When
  698. AF.download(urlString, parameters: ["foo": "bar"]).responseJSON { resp in
  699. response = resp.tryMap { _ in "ignored" }
  700. expectation.fulfill()
  701. }
  702. waitForExpectations(timeout: timeout)
  703. // Then
  704. XCTAssertNotNil(response?.request)
  705. XCTAssertNil(response?.response)
  706. XCTAssertNil(response?.fileURL)
  707. XCTAssertNil(response?.resumeData)
  708. XCTAssertNotNil(response?.error)
  709. XCTAssertEqual(response?.result.isFailure, true)
  710. XCTAssertNotNil(response?.metrics)
  711. }
  712. }
  713. final class DownloadResponseMapErrorTestCase: BaseTestCase {
  714. func testThatMapErrorTransformsFailureValue() {
  715. // Given
  716. let urlString = String.nonexistentDomain
  717. let expectation = self.expectation(description: "request should not succeed")
  718. var response: DownloadResponse<Any, TestError>?
  719. // When
  720. AF.download(urlString).responseJSON { resp in
  721. response = resp.mapError { error in
  722. TestError.error(error: error)
  723. }
  724. expectation.fulfill()
  725. }
  726. waitForExpectations(timeout: timeout)
  727. // Then
  728. XCTAssertNotNil(response?.request)
  729. XCTAssertNil(response?.response)
  730. XCTAssertNil(response?.fileURL)
  731. XCTAssertNil(response?.resumeData)
  732. XCTAssertNotNil(response?.error)
  733. XCTAssertEqual(response?.result.isFailure, true)
  734. guard let error = response?.error, case .error = error else { XCTFail(); return }
  735. XCTAssertNotNil(response?.metrics)
  736. }
  737. func testThatMapErrorPreservesSuccessValue() {
  738. // Given
  739. let expectation = self.expectation(description: "request should succeed")
  740. var response: DownloadResponse<Data, TestError>?
  741. // When
  742. AF.download(.get).responseData { resp in
  743. response = resp.mapError { 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. XCTAssertEqual(response?.result.isSuccess, true)
  753. XCTAssertNotNil(response?.metrics)
  754. }
  755. }
  756. // MARK: -
  757. final class DownloadResponseTryMapErrorTestCase: BaseTestCase {
  758. func testThatTryMapErrorPreservesSuccessValue() {
  759. // Given
  760. let expectation = self.expectation(description: "request should succeed")
  761. var response: DownloadResponse<Data, Error>?
  762. // When
  763. AF.download(.get).responseData { resp in
  764. response = resp.tryMapError { TestError.error(error: $0) }
  765. expectation.fulfill()
  766. }
  767. waitForExpectations(timeout: timeout)
  768. // Then
  769. XCTAssertNotNil(response?.request)
  770. XCTAssertNotNil(response?.response)
  771. XCTAssertNotNil(response?.fileURL)
  772. XCTAssertNil(response?.resumeData)
  773. XCTAssertNil(response?.error)
  774. XCTAssertEqual(response?.result.isSuccess, true)
  775. XCTAssertNotNil(response?.metrics)
  776. }
  777. func testThatTryMapErrorCatchesTransformationError() {
  778. // Given
  779. let urlString = String.nonexistentDomain
  780. let expectation = self.expectation(description: "request should fail")
  781. var response: DownloadResponse<Data, Error>?
  782. // When
  783. AF.download(urlString).responseData { resp in
  784. response = resp.tryMapError { _ in try TransformationError.error.alwaysFails() }
  785. expectation.fulfill()
  786. }
  787. waitForExpectations(timeout: timeout)
  788. // Then
  789. XCTAssertNotNil(response?.request)
  790. XCTAssertNil(response?.response)
  791. XCTAssertNil(response?.fileURL)
  792. XCTAssertNil(response?.resumeData)
  793. XCTAssertNotNil(response?.error)
  794. XCTAssertEqual(response?.result.isFailure, true)
  795. if let error = response?.result.failure {
  796. XCTAssertTrue(error is TransformationError)
  797. } else {
  798. XCTFail("flatMapError should catch the transformation error")
  799. }
  800. XCTAssertNotNil(response?.metrics)
  801. }
  802. func testThatTryMapErrorTransformsError() {
  803. // Given
  804. let urlString = String.nonexistentDomain
  805. let expectation = self.expectation(description: "request should fail")
  806. var response: DownloadResponse<Data, Error>?
  807. // When
  808. AF.download(urlString).responseData { resp in
  809. response = resp.tryMapError { TestError.error(error: $0) }
  810. expectation.fulfill()
  811. }
  812. waitForExpectations(timeout: timeout)
  813. // Then
  814. XCTAssertNotNil(response?.request)
  815. XCTAssertNil(response?.response)
  816. XCTAssertNil(response?.fileURL)
  817. XCTAssertNil(response?.resumeData)
  818. XCTAssertNotNil(response?.error)
  819. XCTAssertEqual(response?.result.isFailure, true)
  820. guard let error = response?.error, case TestError.error = error else { XCTFail(); return }
  821. XCTAssertNotNil(response?.metrics)
  822. }
  823. }