DownloadTests.swift 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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. guard let data = try? Data(contentsOf: fileURL),
  223. let response = try? JSONDecoder().decode(TestResponse.self, from: data) else {
  224. XCTFail("headers parameter in JSON should not be nil")
  225. return
  226. }
  227. XCTAssertEqual(response.headers["Authorization"], "123456")
  228. }
  229. func testThatDownloadingFileAndMovingToDirectoryThatDoesNotExistThrowsError() {
  230. // Given
  231. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  232. let expectation = expectation(description: "Download request should download data but fail to move file")
  233. var response: DownloadResponse<URL?, AFError>?
  234. // When
  235. AF.download(.get, to: { _, _ in (fileURL, []) })
  236. .response { resp in
  237. response = resp
  238. expectation.fulfill()
  239. }
  240. waitForExpectations(timeout: timeout)
  241. // Then
  242. XCTAssertNotNil(response?.request)
  243. XCTAssertNotNil(response?.response)
  244. XCTAssertNil(response?.fileURL)
  245. XCTAssertNil(response?.resumeData)
  246. XCTAssertNotNil(response?.error)
  247. XCTAssertEqual((response?.error?.underlyingError as? CocoaError)?.code, .fileNoSuchFile)
  248. }
  249. func testThatDownloadOptionsCanCreateIntermediateDirectoriesPriorToMovingFile() {
  250. // Given
  251. let fileURL = testDirectoryURL.appendingPathComponent("some/random/folder/test_output.json")
  252. let expectation = expectation(description: "Download request should download data to file: \(fileURL)")
  253. var response: DownloadResponse<URL?, AFError>?
  254. // When
  255. AF.download(.get, to: { _, _ in (fileURL, [.createIntermediateDirectories]) })
  256. .response { resp in
  257. response = resp
  258. expectation.fulfill()
  259. }
  260. waitForExpectations(timeout: timeout)
  261. // Then
  262. XCTAssertNotNil(response?.request)
  263. XCTAssertNotNil(response?.response)
  264. XCTAssertNotNil(response?.fileURL)
  265. XCTAssertNil(response?.resumeData)
  266. XCTAssertNil(response?.error)
  267. }
  268. func testThatDownloadingFileAndMovingToDestinationThatIsOccupiedThrowsError() throws {
  269. // Given
  270. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  271. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  272. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  273. try "random_data".write(to: fileURL, atomically: true, encoding: .utf8)
  274. let expectation = expectation(description: "Download should complete but fail to move file")
  275. var response: DownloadResponse<URL?, AFError>?
  276. // When
  277. AF.download(.get, to: { _, _ in (fileURL, []) })
  278. .response { resp in
  279. response = resp
  280. expectation.fulfill()
  281. }
  282. waitForExpectations(timeout: timeout)
  283. // Then
  284. XCTAssertTrue(directoryCreated)
  285. XCTAssertNotNil(response?.request)
  286. XCTAssertNotNil(response?.response)
  287. XCTAssertNil(response?.fileURL)
  288. XCTAssertNil(response?.resumeData)
  289. XCTAssertNotNil(response?.error)
  290. XCTAssertEqual((response?.error?.underlyingError as? CocoaError)?.code, .fileWriteFileExists)
  291. }
  292. func testThatDownloadOptionsCanRemovePreviousFilePriorToMovingFile() {
  293. // Given
  294. let directoryURL = testDirectoryURL.appendingPathComponent("some/random/folder")
  295. let directoryCreated = FileManager.createDirectory(at: directoryURL)
  296. let fileURL = directoryURL.appendingPathComponent("test_output.json")
  297. let expectation = expectation(description: "Download should complete and move file to URL: \(fileURL)")
  298. var response: DownloadResponse<URL?, AFError>?
  299. // When
  300. AF.download(.get,
  301. to: { _, _ in (fileURL, [.removePreviousFile, .createIntermediateDirectories]) })
  302. .response { resp in
  303. response = resp
  304. expectation.fulfill()
  305. }
  306. waitForExpectations(timeout: timeout)
  307. // Then
  308. XCTAssertTrue(directoryCreated)
  309. XCTAssertNotNil(response?.request)
  310. XCTAssertNotNil(response?.response)
  311. XCTAssertNotNil(response?.fileURL)
  312. XCTAssertNil(response?.resumeData)
  313. XCTAssertNil(response?.error)
  314. }
  315. }
  316. // MARK: -
  317. final class DownloadRequestEventsTestCase: BaseTestCase {
  318. func testThatDownloadRequestTriggersAllAppropriateLifetimeEvents() {
  319. // Given
  320. let eventMonitor = ClosureEventMonitor()
  321. let session = Session(eventMonitors: [eventMonitor])
  322. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  323. let didCreateInitialURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  324. let didCreateURLRequest = expectation(description: "didCreateURLRequest should fire")
  325. let didCreateTask = expectation(description: "didCreateTask should fire")
  326. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  327. let didComplete = expectation(description: "didComplete should fire")
  328. let didWriteData = expectation(description: "didWriteData should fire")
  329. let didFinishDownloading = expectation(description: "didFinishDownloading should fire")
  330. let didFinishWithResult = expectation(description: "didFinishWithResult should fire")
  331. let didCreate = expectation(description: "didCreate should fire")
  332. let didFinish = expectation(description: "didFinish should fire")
  333. let didResume = expectation(description: "didResume should fire")
  334. let didResumeTask = expectation(description: "didResumeTask should fire")
  335. let didParseResponse = expectation(description: "didParseResponse should fire")
  336. let responseHandler = expectation(description: "responseHandler should fire")
  337. var wroteData = false
  338. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  339. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateInitialURLRequest.fulfill() }
  340. eventMonitor.requestDidCreateURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  341. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  342. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  343. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  344. eventMonitor.downloadTaskDidWriteData = { _, _, _, _, _ in
  345. guard !wroteData else { return }
  346. wroteData = true
  347. didWriteData.fulfill()
  348. }
  349. eventMonitor.downloadTaskDidFinishDownloadingToURL = { _, _, _ in didFinishDownloading.fulfill() }
  350. eventMonitor.requestDidFinishDownloadingUsingTaskWithResult = { _, _, _ in didFinishWithResult.fulfill() }
  351. eventMonitor.requestDidCreateDestinationURL = { _, _ in didCreate.fulfill() }
  352. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  353. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  354. eventMonitor.requestDidResumeTask = { _, _ in didResumeTask.fulfill() }
  355. eventMonitor.requestDidParseDownloadResponse = { _, _ in didParseResponse.fulfill() }
  356. // When
  357. let request = session.download(.get).response { _ in
  358. responseHandler.fulfill()
  359. }
  360. waitForExpectations(timeout: timeout)
  361. // Then
  362. XCTAssertEqual(request.state, .finished)
  363. }
  364. func testThatCancelledDownloadRequestTriggersAllAppropriateLifetimeEvents() {
  365. // Given
  366. let eventMonitor = ClosureEventMonitor()
  367. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  368. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  369. let didCreateInitialURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  370. let didCreateURLRequest = expectation(description: "didCreateURLRequest should fire")
  371. let didCreateTask = expectation(description: "didCreateTask should fire")
  372. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  373. let didComplete = expectation(description: "didComplete should fire")
  374. let didFinish = expectation(description: "didFinish should fire")
  375. let didResume = expectation(description: "didResume should fire")
  376. let didResumeTask = expectation(description: "didResumeTask should fire")
  377. let didParseResponse = expectation(description: "didParseResponse should fire")
  378. let didCancel = expectation(description: "didCancel should fire")
  379. let didCancelTask = expectation(description: "didCancelTask should fire")
  380. let responseHandler = expectation(description: "responseHandler should fire")
  381. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  382. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateInitialURLRequest.fulfill() }
  383. eventMonitor.requestDidCreateURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  384. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  385. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  386. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  387. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  388. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  389. eventMonitor.requestDidParseDownloadResponse = { _, _ in didParseResponse.fulfill() }
  390. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  391. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  392. // When
  393. let request = session.download(.delay(5)).response { _ in
  394. responseHandler.fulfill()
  395. }
  396. eventMonitor.requestDidResumeTask = { [unowned request] _, _ in
  397. request.cancel()
  398. didResumeTask.fulfill()
  399. }
  400. request.resume()
  401. waitForExpectations(timeout: timeout)
  402. // Then
  403. XCTAssertEqual(request.state, .cancelled)
  404. }
  405. }
  406. // MARK: -
  407. final class DownloadResumeDataTestCase: BaseTestCase {
  408. func testThatCancelledDownloadRequestDoesNotProduceResumeData() {
  409. // Given
  410. let expectation = expectation(description: "Download should be cancelled")
  411. var cancelled = false
  412. var response: DownloadResponse<URL?, AFError>?
  413. // When
  414. let download = AF.download(.download())
  415. download.downloadProgress { [unowned download] progress in
  416. guard !cancelled else { return }
  417. if progress.fractionCompleted > 0.1 {
  418. download.cancel()
  419. cancelled = true
  420. }
  421. }
  422. download.response { resp in
  423. response = resp
  424. expectation.fulfill()
  425. }
  426. waitForExpectations(timeout: timeout)
  427. // Then
  428. XCTAssertNotNil(response?.request)
  429. XCTAssertNotNil(response?.response)
  430. XCTAssertNil(response?.fileURL)
  431. XCTAssertNotNil(response?.error)
  432. XCTAssertNil(response?.resumeData)
  433. XCTAssertNil(download.resumeData)
  434. }
  435. func testThatDownloadRequestProducesResumeDataOnError() {
  436. // Given
  437. let expectation = expectation(description: "download complete")
  438. var response: DownloadResponse<URL?, AFError>?
  439. // When
  440. let download = AF.download(.download(produceError: true))
  441. download.response { resp in
  442. response = resp
  443. expectation.fulfill()
  444. }
  445. waitForExpectations(timeout: timeout)
  446. // Then
  447. XCTAssertNotNil(response?.request)
  448. XCTAssertNotNil(response?.response)
  449. XCTAssertNil(response?.fileURL)
  450. XCTAssertNotNil(response?.error)
  451. XCTAssertNotNil(response?.resumeData)
  452. XCTAssertNotNil(download.resumeData)
  453. #if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
  454. XCTAssertNotNil(download.error?.downloadResumeData)
  455. XCTAssertEqual(download.error?.downloadResumeData, response?.resumeData)
  456. #endif
  457. XCTAssertEqual(response?.resumeData, download.resumeData)
  458. }
  459. func testThatCancelledDownloadResponseDataMatchesResumeData() {
  460. // Given
  461. let expectation = expectation(description: "Download should be cancelled")
  462. var cancelled = false
  463. var response: DownloadResponse<URL?, AFError>?
  464. // When
  465. let download = AF.download(.download())
  466. download.downloadProgress { [unowned download] progress in
  467. guard !cancelled else { return }
  468. if progress.fractionCompleted > 0.1 {
  469. download.cancel(producingResumeData: true)
  470. cancelled = true
  471. }
  472. }
  473. download.response { resp in
  474. response = resp
  475. expectation.fulfill()
  476. }
  477. waitForExpectations(timeout: timeout)
  478. // Then
  479. XCTAssertNotNil(response?.request)
  480. XCTAssertNotNil(response?.response)
  481. XCTAssertNil(response?.fileURL)
  482. XCTAssertNotNil(response?.error)
  483. XCTAssertNotNil(response?.resumeData)
  484. XCTAssertNotNil(download.resumeData)
  485. XCTAssertEqual(response?.resumeData, download.resumeData)
  486. }
  487. func testThatCancelledDownloadResumeDataIsAvailableWithDecodableResponseSerializer() {
  488. // Given
  489. let expectation = expectation(description: "Download should be cancelled")
  490. var cancelled = false
  491. var response: DownloadResponse<TestResponse, AFError>?
  492. // When
  493. let download = AF.download(.download())
  494. download.downloadProgress { [unowned download] progress in
  495. guard !cancelled else { return }
  496. if progress.fractionCompleted > 0.1 {
  497. download.cancel(producingResumeData: true)
  498. cancelled = true
  499. }
  500. }
  501. download.responseDecodable(of: TestResponse.self) { resp in
  502. response = resp
  503. expectation.fulfill()
  504. }
  505. waitForExpectations(timeout: timeout)
  506. // Then
  507. XCTAssertNotNil(response?.request)
  508. XCTAssertNotNil(response?.response)
  509. XCTAssertNil(response?.fileURL)
  510. XCTAssertEqual(response?.result.isFailure, true)
  511. XCTAssertNotNil(response?.result.failure)
  512. XCTAssertNotNil(response?.resumeData)
  513. XCTAssertNotNil(download.resumeData)
  514. XCTAssertEqual(response?.resumeData, download.resumeData)
  515. }
  516. func testThatCancelledDownloadCanBeResumedWithResumeData() {
  517. // Given
  518. let expectation1 = expectation(description: "Download should be cancelled")
  519. var cancelled = false
  520. var response1: DownloadResponse<Data, AFError>?
  521. // When
  522. let download = AF.download(.download())
  523. download.downloadProgress { [unowned download] progress in
  524. guard !cancelled else { return }
  525. if progress.fractionCompleted > 0.1 {
  526. download.cancel(producingResumeData: true)
  527. cancelled = true
  528. }
  529. }
  530. download.responseData { resp in
  531. response1 = resp
  532. expectation1.fulfill()
  533. }
  534. waitForExpectations(timeout: timeout)
  535. guard let resumeData = download.resumeData else {
  536. XCTFail("resumeData should not be nil")
  537. return
  538. }
  539. let expectation2 = expectation(description: "Download should complete")
  540. var progressValues: [Double] = []
  541. var response2: DownloadResponse<Data, AFError>?
  542. AF.download(resumingWith: resumeData)
  543. .downloadProgress { progress in
  544. progressValues.append(progress.fractionCompleted)
  545. }
  546. .responseData { resp in
  547. response2 = resp
  548. expectation2.fulfill()
  549. }
  550. waitForExpectations(timeout: timeout)
  551. // Then
  552. XCTAssertNotNil(response1?.request)
  553. XCTAssertNotNil(response1?.response)
  554. XCTAssertNil(response1?.fileURL)
  555. XCTAssertEqual(response1?.result.isFailure, true)
  556. XCTAssertNotNil(response1?.result.failure)
  557. XCTAssertNotNil(response2?.response)
  558. XCTAssertNotNil(response2?.fileURL)
  559. XCTAssertEqual(response2?.result.isSuccess, true)
  560. XCTAssertNil(response2?.result.failure)
  561. progressValues.forEach { XCTAssertGreaterThanOrEqual($0, 0.1) }
  562. }
  563. func testThatCancelledDownloadProducesMatchingResumeData() {
  564. // Given
  565. let expectation = expectation(description: "Download should be cancelled")
  566. var cancelled = false
  567. var receivedResumeData: Data?
  568. var response: DownloadResponse<URL?, AFError>?
  569. // When
  570. let download = AF.download(.download())
  571. download.downloadProgress { [unowned download] progress in
  572. guard !cancelled else { return }
  573. if progress.fractionCompleted > 0.1 {
  574. download.cancel { receivedResumeData = $0 }
  575. cancelled = true
  576. }
  577. }
  578. download.response { resp in
  579. response = resp
  580. expectation.fulfill()
  581. }
  582. waitForExpectations(timeout: timeout)
  583. // Then
  584. XCTAssertNotNil(response?.request)
  585. XCTAssertNotNil(response?.response)
  586. XCTAssertNil(response?.fileURL)
  587. XCTAssertNotNil(response?.error)
  588. XCTAssertNotNil(response?.resumeData)
  589. XCTAssertNotNil(download.resumeData)
  590. XCTAssertEqual(response?.resumeData, download.resumeData)
  591. XCTAssertEqual(response?.resumeData, receivedResumeData)
  592. XCTAssertEqual(download.resumeData, receivedResumeData)
  593. }
  594. }
  595. // MARK: -
  596. final class DownloadResponseMapTestCase: BaseTestCase {
  597. func testThatMapTransformsSuccessValue() {
  598. // Given
  599. let expectation = expectation(description: "request should succeed")
  600. var response: DownloadResponse<String, AFError>?
  601. // When
  602. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  603. response = resp.map { response in
  604. response.args["foo"] ?? "invalid"
  605. }
  606. expectation.fulfill()
  607. }
  608. waitForExpectations(timeout: timeout)
  609. // Then
  610. XCTAssertNotNil(response?.request)
  611. XCTAssertNotNil(response?.response)
  612. XCTAssertNotNil(response?.fileURL)
  613. XCTAssertNil(response?.resumeData)
  614. XCTAssertNil(response?.error)
  615. XCTAssertEqual(response?.result.success, "bar")
  616. XCTAssertNotNil(response?.metrics)
  617. }
  618. func testThatMapPreservesFailureError() {
  619. // Given
  620. let urlString = String.invalidURL
  621. let expectation = expectation(description: "request should fail with invalid URL")
  622. var response: DownloadResponse<String, AFError>?
  623. // When
  624. AF.download(urlString, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  625. response = resp.map { _ in "ignored" }
  626. expectation.fulfill()
  627. }
  628. waitForExpectations(timeout: timeout)
  629. // Then
  630. XCTAssertNotNil(response?.request)
  631. XCTAssertNil(response?.response)
  632. XCTAssertNil(response?.fileURL)
  633. XCTAssertNil(response?.resumeData)
  634. XCTAssertNotNil(response?.error)
  635. XCTAssertEqual(response?.result.isFailure, true)
  636. XCTAssertNotNil(response?.metrics)
  637. }
  638. }
  639. // MARK: -
  640. final class DownloadResponseTryMapTestCase: BaseTestCase {
  641. func testThatTryMapTransformsSuccessValue() {
  642. // Given
  643. let expectation = expectation(description: "request should succeed")
  644. var response: DownloadResponse<String, Error>?
  645. // When
  646. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  647. response = resp.tryMap { response in
  648. response.args["foo"] ?? "invalid"
  649. }
  650. expectation.fulfill()
  651. }
  652. waitForExpectations(timeout: timeout)
  653. // Then
  654. XCTAssertNotNil(response?.request)
  655. XCTAssertNotNil(response?.response)
  656. XCTAssertNotNil(response?.fileURL)
  657. XCTAssertNil(response?.resumeData)
  658. XCTAssertNil(response?.error)
  659. XCTAssertEqual(response?.result.success, "bar")
  660. XCTAssertNotNil(response?.metrics)
  661. }
  662. func testThatTryMapCatchesTransformationError() {
  663. // Given
  664. struct TransformError: Error {}
  665. let expectation = expectation(description: "request should succeed")
  666. var response: DownloadResponse<String, Error>?
  667. // When
  668. AF.download(.get, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  669. response = resp.tryMap { _ in
  670. throw TransformError()
  671. }
  672. expectation.fulfill()
  673. }
  674. waitForExpectations(timeout: timeout)
  675. // Then
  676. XCTAssertNotNil(response?.request)
  677. XCTAssertNotNil(response?.response)
  678. XCTAssertNotNil(response?.fileURL)
  679. XCTAssertNil(response?.resumeData)
  680. if let error = response?.result.failure {
  681. XCTAssertTrue(error is TransformError)
  682. } else {
  683. XCTFail("flatMap should catch the transformation error")
  684. }
  685. XCTAssertNotNil(response?.metrics)
  686. }
  687. func testThatTryMapPreservesFailureError() {
  688. // Given
  689. let urlString = String.invalidURL
  690. let expectation = expectation(description: "request should fail with 404")
  691. var response: DownloadResponse<String, Error>?
  692. // When
  693. AF.download(urlString, parameters: ["foo": "bar"]).responseDecodable(of: TestResponse.self) { resp in
  694. response = resp.tryMap { _ in "ignored" }
  695. expectation.fulfill()
  696. }
  697. waitForExpectations(timeout: timeout)
  698. // Then
  699. XCTAssertNotNil(response?.request)
  700. XCTAssertNil(response?.response)
  701. XCTAssertNil(response?.fileURL)
  702. XCTAssertNil(response?.resumeData)
  703. XCTAssertNotNil(response?.error)
  704. XCTAssertEqual(response?.result.isFailure, true)
  705. XCTAssertNotNil(response?.metrics)
  706. }
  707. }
  708. final class DownloadResponseMapErrorTestCase: BaseTestCase {
  709. func testThatMapErrorTransformsFailureValue() {
  710. // Given
  711. let urlString = String.invalidURL
  712. let expectation = expectation(description: "request should not succeed")
  713. var response: DownloadResponse<TestResponse, TestError>?
  714. // When
  715. AF.download(urlString).responseDecodable(of: TestResponse.self) { resp in
  716. response = resp.mapError { error in
  717. TestError.error(error: error)
  718. }
  719. expectation.fulfill()
  720. }
  721. waitForExpectations(timeout: timeout)
  722. // Then
  723. XCTAssertNotNil(response?.request)
  724. XCTAssertNil(response?.response)
  725. XCTAssertNil(response?.fileURL)
  726. XCTAssertNil(response?.resumeData)
  727. XCTAssertNotNil(response?.error)
  728. XCTAssertEqual(response?.result.isFailure, true)
  729. guard let error = response?.error, case .error = error else { XCTFail(); return }
  730. XCTAssertNotNil(response?.metrics)
  731. }
  732. func testThatMapErrorPreservesSuccessValue() {
  733. // Given
  734. let expectation = expectation(description: "request should succeed")
  735. var response: DownloadResponse<Data, TestError>?
  736. // When
  737. AF.download(.get).responseData { resp in
  738. response = resp.mapError { TestError.error(error: $0) }
  739. expectation.fulfill()
  740. }
  741. waitForExpectations(timeout: timeout)
  742. // Then
  743. XCTAssertNotNil(response?.request)
  744. XCTAssertNotNil(response?.response)
  745. XCTAssertNotNil(response?.fileURL)
  746. XCTAssertNil(response?.resumeData)
  747. XCTAssertEqual(response?.result.isSuccess, true)
  748. XCTAssertNotNil(response?.metrics)
  749. }
  750. }
  751. // MARK: -
  752. final class DownloadResponseTryMapErrorTestCase: BaseTestCase {
  753. func testThatTryMapErrorPreservesSuccessValue() {
  754. // Given
  755. let expectation = expectation(description: "request should succeed")
  756. var response: DownloadResponse<Data, Error>?
  757. // When
  758. AF.download(.get).responseData { resp in
  759. response = resp.tryMapError { TestError.error(error: $0) }
  760. expectation.fulfill()
  761. }
  762. waitForExpectations(timeout: timeout)
  763. // Then
  764. XCTAssertNotNil(response?.request)
  765. XCTAssertNotNil(response?.response)
  766. XCTAssertNotNil(response?.fileURL)
  767. XCTAssertNil(response?.resumeData)
  768. XCTAssertNil(response?.error)
  769. XCTAssertEqual(response?.result.isSuccess, true)
  770. XCTAssertNotNil(response?.metrics)
  771. }
  772. func testThatTryMapErrorCatchesTransformationError() {
  773. // Given
  774. let urlString = String.invalidURL
  775. let expectation = expectation(description: "request should fail")
  776. var response: DownloadResponse<Data, Error>?
  777. // When
  778. AF.download(urlString).responseData { resp in
  779. response = resp.tryMapError { _ in try TransformationError.error.alwaysFails() }
  780. expectation.fulfill()
  781. }
  782. waitForExpectations(timeout: timeout)
  783. // Then
  784. XCTAssertNotNil(response?.request)
  785. XCTAssertNil(response?.response)
  786. XCTAssertNil(response?.fileURL)
  787. XCTAssertNil(response?.resumeData)
  788. XCTAssertNotNil(response?.error)
  789. XCTAssertEqual(response?.result.isFailure, true)
  790. if let error = response?.result.failure {
  791. XCTAssertTrue(error is TransformationError)
  792. } else {
  793. XCTFail("flatMapError should catch the transformation error")
  794. }
  795. XCTAssertNotNil(response?.metrics)
  796. }
  797. func testThatTryMapErrorTransformsError() {
  798. // Given
  799. let urlString = String.invalidURL
  800. let expectation = expectation(description: "request should fail")
  801. var response: DownloadResponse<Data, Error>?
  802. // When
  803. AF.download(urlString).responseData { resp in
  804. response = resp.tryMapError { TestError.error(error: $0) }
  805. expectation.fulfill()
  806. }
  807. waitForExpectations(timeout: timeout)
  808. // Then
  809. XCTAssertNotNil(response?.request)
  810. XCTAssertNil(response?.response)
  811. XCTAssertNil(response?.fileURL)
  812. XCTAssertNil(response?.resumeData)
  813. XCTAssertNotNil(response?.error)
  814. XCTAssertEqual(response?.result.isFailure, true)
  815. guard let error = response?.error, case TestError.error = error else { XCTFail(); return }
  816. XCTAssertNotNil(response?.metrics)
  817. }
  818. }