SessionTests.swift 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765
  1. //
  2. // SessionTests.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. @testable import Alamofire
  25. import Foundation
  26. import XCTest
  27. final class SessionTestCase: BaseTestCase {
  28. // MARK: Helper Types
  29. private class HTTPMethodAdapter: RequestInterceptor {
  30. let method: HTTPMethod
  31. let throwsError: Bool
  32. var adaptedCount = 0
  33. init(method: HTTPMethod, throwsError: Bool = false) {
  34. self.method = method
  35. self.throwsError = throwsError
  36. }
  37. func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  38. adaptedCount += 1
  39. let result: Result<URLRequest, Error> = Result {
  40. guard !throwsError else { throw AFError.invalidURL(url: "") }
  41. var urlRequest = urlRequest
  42. urlRequest.httpMethod = method.rawValue
  43. return urlRequest
  44. }
  45. completion(result)
  46. }
  47. }
  48. private class HeaderAdapter: RequestInterceptor {
  49. let headers: HTTPHeaders
  50. let throwsError: Bool
  51. var adaptedCount = 0
  52. init(headers: HTTPHeaders = ["field": "value"], throwsError: Bool = false) {
  53. self.headers = headers
  54. self.throwsError = throwsError
  55. }
  56. func adapt(_ urlRequest: URLRequest, using state: RequestAdapterState, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  57. adaptedCount += 1
  58. let result: Result<URLRequest, Error> = Result {
  59. guard !throwsError else { throw AFError.invalidURL(url: "") }
  60. var urlRequest = urlRequest
  61. var finalHeaders = urlRequest.headers
  62. headers.forEach { finalHeaders.add($0) }
  63. urlRequest.headers = finalHeaders
  64. return urlRequest
  65. }
  66. completion(result)
  67. }
  68. }
  69. private class RequestHandler: RequestInterceptor {
  70. var adaptCalledCount = 0
  71. var adaptedCount = 0
  72. var retryCount = 0
  73. var retryCalledCount = 0
  74. var retryErrors: [Error] = []
  75. var shouldApplyAuthorizationHeader = false
  76. var throwsErrorOnFirstAdapt = false
  77. var throwsErrorOnSecondAdapt = false
  78. var throwsErrorOnRetry = false
  79. var shouldRetry = true
  80. var retryDelay: TimeInterval?
  81. func adapt(
  82. _ urlRequest: URLRequest,
  83. using state: RequestAdapterState,
  84. completion: @escaping (Result<URLRequest, Error>) -> Void) {
  85. adaptCalledCount += 1
  86. let result: Result<URLRequest, Error> = Result {
  87. if throwsErrorOnFirstAdapt {
  88. throwsErrorOnFirstAdapt = false
  89. throw AFError.invalidURL(url: "/adapt/error/1")
  90. }
  91. if throwsErrorOnSecondAdapt && adaptedCount == 1 {
  92. throwsErrorOnSecondAdapt = false
  93. throw AFError.invalidURL(url: "/adapt/error/2")
  94. }
  95. var urlRequest = urlRequest
  96. adaptedCount += 1
  97. if shouldApplyAuthorizationHeader && adaptedCount > 1 {
  98. urlRequest.headers.update(.authorization(username: "user", password: "password"))
  99. }
  100. return urlRequest
  101. }
  102. completion(result)
  103. }
  104. func retry(_ request: Request,
  105. for session: Session,
  106. dueTo error: Error,
  107. completion: @escaping (RetryResult) -> Void) {
  108. retryCalledCount += 1
  109. if throwsErrorOnRetry {
  110. let error = AFError.invalidURL(url: "/invalid/url/\(retryCalledCount)")
  111. completion(.doNotRetryWithError(error))
  112. return
  113. }
  114. guard shouldRetry else { completion(.doNotRetry); return }
  115. retryCount += 1
  116. retryErrors.append(error)
  117. if retryCount < 2 {
  118. if let retryDelay = retryDelay {
  119. completion(.retryWithDelay(retryDelay))
  120. } else {
  121. completion(.retry)
  122. }
  123. } else {
  124. completion(.doNotRetry)
  125. }
  126. }
  127. }
  128. private class UploadHandler: RequestInterceptor {
  129. var adaptCalledCount = 0
  130. var adaptedCount = 0
  131. var retryCalledCount = 0
  132. var retryCount = 0
  133. var retryErrors: [Error] = []
  134. func adapt(_ urlRequest: URLRequest,
  135. using state: RequestAdapterState,
  136. completion: @escaping (Result<URLRequest, Error>) -> Void) {
  137. adaptCalledCount += 1
  138. let result: Result<URLRequest, Error> = Result {
  139. adaptedCount += 1
  140. if adaptedCount == 1 { throw AFError.invalidURL(url: "") }
  141. return urlRequest
  142. }
  143. completion(result)
  144. }
  145. func retry(_ request: Request,
  146. for session: Session,
  147. dueTo error: Error,
  148. completion: @escaping (RetryResult) -> Void) {
  149. retryCalledCount += 1
  150. retryCount += 1
  151. retryErrors.append(error)
  152. completion(.retry)
  153. }
  154. }
  155. // MARK: Tests - Initialization
  156. func testInitializerWithDefaultArguments() {
  157. // Given, When
  158. let session = Session()
  159. // Then
  160. XCTAssertNotNil(session.session.delegate, "session delegate should not be nil")
  161. XCTAssertTrue(session.delegate === session.session.delegate, "manager delegate should equal session delegate")
  162. XCTAssertNil(session.serverTrustManager, "session server trust policy manager should be nil")
  163. }
  164. func testInitializerWithSpecifiedArguments() {
  165. // Given
  166. let configuration = URLSessionConfiguration.default
  167. let delegate = SessionDelegate()
  168. let serverTrustManager = ServerTrustManager(evaluators: [:])
  169. // When
  170. let session = Session(configuration: configuration,
  171. delegate: delegate,
  172. serverTrustManager: serverTrustManager)
  173. // Then
  174. XCTAssertNotNil(session.session.delegate, "session delegate should not be nil")
  175. XCTAssertTrue(session.delegate === session.session.delegate, "manager delegate should equal session delegate")
  176. XCTAssertNotNil(session.serverTrustManager, "session server trust policy manager should not be nil")
  177. }
  178. func testThatSessionInitializerSucceedsWithDefaultArguments() {
  179. // Given
  180. let delegate = SessionDelegate()
  181. let underlyingQueue = DispatchQueue(label: "underlyingQueue")
  182. let urlSession: URLSession = {
  183. let configuration = URLSessionConfiguration.default
  184. let queue = OperationQueue(underlyingQueue: underlyingQueue, name: "delegateQueue")
  185. return URLSession(configuration: configuration, delegate: delegate, delegateQueue: queue)
  186. }()
  187. // When
  188. let session = Session(session: urlSession, delegate: delegate, rootQueue: underlyingQueue)
  189. // Then
  190. XCTAssertTrue(session.delegate === session.session.delegate, "manager delegate should equal session delegate")
  191. XCTAssertNil(session.serverTrustManager, "session server trust policy manager should be nil")
  192. }
  193. func testThatSessionInitializerSucceedsWithSpecifiedArguments() {
  194. // Given
  195. let delegate = SessionDelegate()
  196. let underlyingQueue = DispatchQueue(label: "underlyingQueue")
  197. let urlSession: URLSession = {
  198. let configuration = URLSessionConfiguration.default
  199. let queue = OperationQueue(underlyingQueue: underlyingQueue, name: "delegateQueue")
  200. return URLSession(configuration: configuration, delegate: delegate, delegateQueue: queue)
  201. }()
  202. let serverTrustManager = ServerTrustManager(evaluators: [:])
  203. // When
  204. let session = Session(session: urlSession,
  205. delegate: delegate,
  206. rootQueue: underlyingQueue,
  207. serverTrustManager: serverTrustManager)
  208. // Then
  209. XCTAssertTrue(session.delegate === session.session.delegate, "manager delegate should equal session delegate")
  210. XCTAssertNotNil(session.serverTrustManager, "session server trust policy manager should not be nil")
  211. }
  212. // MARK: Tests - Default HTTP Headers
  213. func testDefaultUserAgentHeader() {
  214. // Given, When
  215. let userAgent = HTTPHeaders.default["User-Agent"]
  216. // Then
  217. let osNameVersion: String = {
  218. let version = ProcessInfo.processInfo.operatingSystemVersion
  219. let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
  220. let osName: String = {
  221. #if os(iOS)
  222. #if targetEnvironment(macCatalyst)
  223. return "macOS(Catalyst)"
  224. #else
  225. return "iOS"
  226. #endif
  227. #elseif os(watchOS)
  228. return "watchOS"
  229. #elseif os(tvOS)
  230. return "tvOS"
  231. #elseif os(macOS)
  232. return "macOS"
  233. #elseif os(Linux)
  234. return "Linux"
  235. #else
  236. return "Unknown"
  237. #endif
  238. }()
  239. return "\(osName) \(versionString)"
  240. }()
  241. let alamofireVersion = "Alamofire/\(Alamofire.version)"
  242. XCTAssertTrue(userAgent?.contains(alamofireVersion) == true)
  243. XCTAssertTrue(userAgent?.contains(osNameVersion) == true)
  244. XCTAssertTrue(userAgent?.contains("xctest/") == true)
  245. }
  246. // MARK: Tests - Supported Accept-Encodings
  247. func testDefaultAcceptEncodingSupportsAppropriateEncodingsOnAppropriateSystems() {
  248. // Given
  249. let brotliExpectation = expectation(description: "brotli request should complete")
  250. let gzipExpectation = expectation(description: "gzip request should complete")
  251. let deflateExpectation = expectation(description: "deflate request should complete")
  252. var brotliResponse: DataResponse<TestResponse, AFError>?
  253. var gzipResponse: DataResponse<TestResponse, AFError>?
  254. var deflateResponse: DataResponse<TestResponse, AFError>?
  255. // When
  256. AF.request(.compression(.brotli)).responseDecodable(of: TestResponse.self) { response in
  257. brotliResponse = response
  258. brotliExpectation.fulfill()
  259. }
  260. AF.request(.compression(.gzip)).responseDecodable(of: TestResponse.self) { response in
  261. gzipResponse = response
  262. gzipExpectation.fulfill()
  263. }
  264. AF.request(.compression(.deflate)).responseDecodable(of: TestResponse.self) { response in
  265. deflateResponse = response
  266. deflateExpectation.fulfill()
  267. }
  268. waitForExpectations(timeout: timeout)
  269. // Then
  270. if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
  271. XCTAssertTrue(brotliResponse?.result.isSuccess == true)
  272. } else {
  273. XCTAssertTrue(brotliResponse?.result.isFailure == true)
  274. }
  275. XCTAssertTrue(gzipResponse?.result.isSuccess == true)
  276. XCTAssertTrue(deflateResponse?.result.isSuccess == true)
  277. }
  278. // MARK: Tests - Start Requests Immediately
  279. func testSetStartRequestsImmediatelyToFalseAndResumeRequest() {
  280. // Given
  281. let session = Session(startRequestsImmediately: false)
  282. let url = Endpoint().url
  283. let urlRequest = URLRequest(url: url)
  284. let expectation = self.expectation(description: "\(url)")
  285. var response: HTTPURLResponse?
  286. // When
  287. session.request(urlRequest)
  288. .response { resp in
  289. response = resp.response
  290. expectation.fulfill()
  291. }
  292. .resume()
  293. waitForExpectations(timeout: timeout)
  294. // Then
  295. XCTAssertNotNil(response, "response should not be nil")
  296. XCTAssertTrue(response?.statusCode == 200, "response status code should be 200")
  297. }
  298. func testSetStartRequestsImmediatelyToFalseAndCancelledCallsResponseHandlers() {
  299. // Given
  300. let session = Session(startRequestsImmediately: false)
  301. let url = Endpoint().url
  302. let urlRequest = URLRequest(url: url)
  303. let expectation = self.expectation(description: "\(url)")
  304. var response: DataResponse<Data?, AFError>?
  305. // When
  306. let request = session.request(urlRequest)
  307. .cancel()
  308. .response { resp in
  309. response = resp
  310. expectation.fulfill()
  311. }
  312. waitForExpectations(timeout: timeout)
  313. // Then
  314. XCTAssertNotNil(response, "response should not be nil")
  315. XCTAssertTrue(request.isCancelled)
  316. XCTAssertTrue((request.task == nil) || (request.task?.state == .canceling || request.task?.state == .completed))
  317. XCTAssertEqual(request.error?.isExplicitlyCancelledError, true)
  318. }
  319. func testSetStartRequestsImmediatelyToFalseAndResumeThenCancelRequestHasCorrectOutput() {
  320. // Given
  321. let session = Session(startRequestsImmediately: false)
  322. let url = Endpoint().url
  323. let urlRequest = URLRequest(url: url)
  324. let expectation = self.expectation(description: "\(url)")
  325. var response: DataResponse<Data?, AFError>?
  326. // When
  327. let request = session.request(urlRequest)
  328. .response { resp in
  329. response = resp
  330. expectation.fulfill()
  331. }
  332. .resume()
  333. .cancel()
  334. waitForExpectations(timeout: timeout)
  335. // Then
  336. XCTAssertNotNil(response, "response should not be nil")
  337. XCTAssertTrue(request.isCancelled)
  338. XCTAssertTrue((request.task == nil) || (request.task?.state == .canceling || request.task?.state == .completed))
  339. XCTAssertEqual(request.error?.isExplicitlyCancelledError, true)
  340. }
  341. func testSetStartRequestsImmediatelyToFalseAndCancelThenResumeRequestDoesntCreateTaskAndStaysCancelled() {
  342. // Given
  343. let session = Session(startRequestsImmediately: false)
  344. let url = Endpoint().url
  345. let urlRequest = URLRequest(url: url)
  346. let expectation = self.expectation(description: "\(url)")
  347. var response: DataResponse<Data?, AFError>?
  348. // When
  349. let request = session.request(urlRequest)
  350. .response { resp in
  351. response = resp
  352. expectation.fulfill()
  353. }
  354. .cancel()
  355. .resume()
  356. waitForExpectations(timeout: timeout)
  357. // Then
  358. XCTAssertNotNil(response, "response should not be nil")
  359. XCTAssertTrue(request.isCancelled)
  360. XCTAssertTrue((request.task == nil) || (request.task?.state == .canceling || request.task?.state == .completed))
  361. XCTAssertEqual(request.error?.isExplicitlyCancelledError, true)
  362. }
  363. // MARK: Tests - Deinitialization
  364. func testReleasingManagerWithPendingRequestDeinitializesSuccessfully() {
  365. // Given
  366. let monitor = ClosureEventMonitor()
  367. let expectation = self.expectation(description: "Request created")
  368. monitor.requestDidCreateTask = { _, _ in expectation.fulfill() }
  369. var session: Session? = Session(startRequestsImmediately: false, eventMonitors: [monitor])
  370. // When
  371. let request = session?.request(.default)
  372. session = nil
  373. waitForExpectations(timeout: timeout)
  374. // Then
  375. XCTAssertEqual(request?.task?.state, .suspended)
  376. XCTAssertNil(session, "manager should be nil")
  377. }
  378. func testReleasingManagerWithPendingCanceledRequestDeinitializesSuccessfully() {
  379. // Given
  380. var session: Session? = Session(startRequestsImmediately: false)
  381. // When
  382. let request = session?.request(.default)
  383. request?.cancel()
  384. session = nil
  385. let state = request?.state
  386. // Then
  387. XCTAssertTrue(state == .cancelled, "state should be .cancelled")
  388. XCTAssertNil(session, "manager should be nil")
  389. }
  390. // MARK: Tests - Bad Requests
  391. func testThatDataRequestWithInvalidURLStringThrowsResponseHandlerError() {
  392. // Given
  393. let session = Session()
  394. let url = Endpoint().url.absoluteString.appending("/äëïöü")
  395. let expectation = self.expectation(description: "Request should fail with error")
  396. var response: DataResponse<Data?, AFError>?
  397. // When
  398. session.request(url).response { resp in
  399. response = resp
  400. expectation.fulfill()
  401. }
  402. waitForExpectations(timeout: timeout)
  403. // Then
  404. XCTAssertNil(response?.request)
  405. XCTAssertNil(response?.response)
  406. XCTAssertNil(response?.data)
  407. XCTAssertNotNil(response?.error)
  408. XCTAssertEqual(response?.error?.isInvalidURLError, true)
  409. XCTAssertEqual(response?.error?.urlConvertible as? String, url)
  410. }
  411. func testThatDownloadRequestWithInvalidURLStringThrowsResponseHandlerError() {
  412. // Given
  413. let session = Session()
  414. let url = Endpoint().url.absoluteString.appending("/äëïöü")
  415. let expectation = self.expectation(description: "Download should fail with error")
  416. var response: DownloadResponse<URL?, AFError>?
  417. // When
  418. session.download(url).response { resp in
  419. response = resp
  420. expectation.fulfill()
  421. }
  422. waitForExpectations(timeout: timeout)
  423. // Then
  424. XCTAssertNil(response?.request)
  425. XCTAssertNil(response?.response)
  426. XCTAssertNil(response?.fileURL)
  427. XCTAssertNil(response?.resumeData)
  428. XCTAssertNotNil(response?.error)
  429. XCTAssertEqual(response?.error?.isInvalidURLError, true)
  430. XCTAssertEqual(response?.error?.urlConvertible as? String, url)
  431. }
  432. func testThatUploadDataRequestWithInvalidURLStringThrowsResponseHandlerError() {
  433. // Given
  434. let session = Session()
  435. let url = Endpoint().url.absoluteString.appending("/äëïöü")
  436. let expectation = self.expectation(description: "Upload should fail with error")
  437. var response: DataResponse<Data?, AFError>?
  438. // When
  439. session.upload(Data(), to: url).response { resp in
  440. response = resp
  441. expectation.fulfill()
  442. }
  443. waitForExpectations(timeout: timeout)
  444. // Then
  445. XCTAssertNil(response?.request)
  446. XCTAssertNil(response?.response)
  447. XCTAssertNil(response?.data)
  448. XCTAssertNotNil(response?.error)
  449. XCTAssertEqual(response?.error?.isInvalidURLError, true)
  450. XCTAssertEqual(response?.error?.urlConvertible as? String, url)
  451. }
  452. func testThatUploadFileRequestWithInvalidURLStringThrowsResponseHandlerError() {
  453. // Given
  454. let session = Session()
  455. let url = Endpoint().url.absoluteString.appending("/äëïöü")
  456. let expectation = self.expectation(description: "Upload should fail with error")
  457. var response: DataResponse<Data?, AFError>?
  458. // When
  459. session.upload(URL(fileURLWithPath: "/invalid"), to: url).response { resp in
  460. response = resp
  461. expectation.fulfill()
  462. }
  463. waitForExpectations(timeout: timeout)
  464. // Then
  465. XCTAssertNil(response?.request)
  466. XCTAssertNil(response?.response)
  467. XCTAssertNil(response?.data)
  468. XCTAssertNotNil(response?.error)
  469. XCTAssertEqual(response?.error?.isInvalidURLError, true)
  470. XCTAssertEqual(response?.error?.urlConvertible as? String, url)
  471. }
  472. func testThatUploadStreamRequestWithInvalidURLStringThrowsResponseHandlerError() {
  473. // Given
  474. let session = Session()
  475. let url = Endpoint().url.absoluteString.appending("/äëïöü")
  476. let expectation = self.expectation(description: "Upload should fail with error")
  477. var response: DataResponse<Data?, AFError>?
  478. // When
  479. session.upload(InputStream(data: Data()), to: url).response { resp in
  480. response = resp
  481. expectation.fulfill()
  482. }
  483. waitForExpectations(timeout: timeout)
  484. // Then
  485. XCTAssertNil(response?.request)
  486. XCTAssertNil(response?.response)
  487. XCTAssertNil(response?.data)
  488. XCTAssertNotNil(response?.error)
  489. XCTAssertEqual(response?.error?.isInvalidURLError, true)
  490. XCTAssertEqual(response?.error?.urlConvertible as? String, url)
  491. }
  492. // MARK: Tests - Request Adapter
  493. func testThatSessionCallsRequestAdaptersWhenCreatingDataRequest() {
  494. // Given
  495. let endpoint = Endpoint()
  496. let methodAdapter = HTTPMethodAdapter(method: .post)
  497. let headerAdapter = HeaderAdapter()
  498. let monitor = ClosureEventMonitor()
  499. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  500. // When
  501. let expectation1 = expectation(description: "Request 1 created")
  502. monitor.requestDidCreateTask = { _, _ in expectation1.fulfill() }
  503. let request1 = session.request(endpoint)
  504. waitForExpectations(timeout: timeout)
  505. let expectation2 = expectation(description: "Request 2 created")
  506. monitor.requestDidCreateTask = { _, _ in expectation2.fulfill() }
  507. let request2 = session.request(endpoint, interceptor: headerAdapter)
  508. waitForExpectations(timeout: timeout)
  509. // Then
  510. XCTAssertEqual(request1.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  511. XCTAssertEqual(request2.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  512. XCTAssertEqual(request2.task?.originalRequest?.allHTTPHeaderFields?.count, 1)
  513. XCTAssertEqual(methodAdapter.adaptedCount, 2)
  514. XCTAssertEqual(headerAdapter.adaptedCount, 1)
  515. }
  516. func testThatSessionCallsRequestAdaptersWhenCreatingDownloadRequest() {
  517. // Given
  518. let endpoint = Endpoint()
  519. let methodAdapter = HTTPMethodAdapter(method: .post)
  520. let headerAdapter = HeaderAdapter()
  521. let monitor = ClosureEventMonitor()
  522. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  523. // When
  524. let expectation1 = expectation(description: "Request 1 created")
  525. monitor.requestDidCreateTask = { _, _ in expectation1.fulfill() }
  526. let request1 = session.download(endpoint)
  527. waitForExpectations(timeout: timeout)
  528. let expectation2 = expectation(description: "Request 2 created")
  529. monitor.requestDidCreateTask = { _, _ in expectation2.fulfill() }
  530. let request2 = session.download(endpoint, interceptor: headerAdapter)
  531. waitForExpectations(timeout: timeout)
  532. // Then
  533. XCTAssertEqual(request1.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  534. XCTAssertEqual(request2.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  535. XCTAssertEqual(request2.task?.originalRequest?.allHTTPHeaderFields?.count, 1)
  536. XCTAssertEqual(methodAdapter.adaptedCount, 2)
  537. XCTAssertEqual(headerAdapter.adaptedCount, 1)
  538. }
  539. func testThatSessionCallsRequestAdaptersWhenCreatingUploadRequestWithData() {
  540. // Given
  541. let data = Data("data".utf8)
  542. let endpoint = Endpoint.method(.post)
  543. let methodAdapter = HTTPMethodAdapter(method: .get)
  544. let headerAdapter = HeaderAdapter()
  545. let monitor = ClosureEventMonitor()
  546. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  547. // When
  548. let expectation1 = expectation(description: "Request 1 created")
  549. monitor.requestDidCreateTask = { _, _ in expectation1.fulfill() }
  550. let request1 = session.upload(data, to: endpoint)
  551. waitForExpectations(timeout: timeout)
  552. let expectation2 = expectation(description: "Request 2 created")
  553. monitor.requestDidCreateTask = { _, _ in expectation2.fulfill() }
  554. let request2 = session.upload(data, to: endpoint, interceptor: headerAdapter)
  555. waitForExpectations(timeout: timeout)
  556. // Then
  557. XCTAssertEqual(request1.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  558. XCTAssertEqual(request2.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  559. XCTAssertEqual(request2.task?.originalRequest?.allHTTPHeaderFields?.count, 1)
  560. XCTAssertEqual(methodAdapter.adaptedCount, 2)
  561. XCTAssertEqual(headerAdapter.adaptedCount, 1)
  562. }
  563. func testThatSessionCallsRequestAdaptersWhenCreatingUploadRequestWithFile() {
  564. // Given
  565. let fileURL = URL(fileURLWithPath: "/path/to/some/file.txt")
  566. let endpoint = Endpoint.method(.post)
  567. let methodAdapter = HTTPMethodAdapter(method: .get)
  568. let headerAdapter = HeaderAdapter()
  569. let monitor = ClosureEventMonitor()
  570. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  571. // When
  572. let expectation1 = expectation(description: "Request 1 created")
  573. monitor.requestDidCreateTask = { _, _ in expectation1.fulfill() }
  574. let request1 = session.upload(fileURL, to: endpoint)
  575. waitForExpectations(timeout: timeout)
  576. let expectation2 = expectation(description: "Request 2 created")
  577. monitor.requestDidCreateTask = { _, _ in expectation2.fulfill() }
  578. let request2 = session.upload(fileURL, to: endpoint, interceptor: headerAdapter)
  579. waitForExpectations(timeout: timeout)
  580. // Then
  581. XCTAssertEqual(request1.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  582. XCTAssertEqual(request2.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  583. XCTAssertEqual(request2.task?.originalRequest?.allHTTPHeaderFields?.count, 1)
  584. XCTAssertEqual(methodAdapter.adaptedCount, 2)
  585. XCTAssertEqual(headerAdapter.adaptedCount, 1)
  586. }
  587. func testThatSessionCallsRequestAdaptersWhenCreatingUploadRequestWithInputStream() {
  588. // Given
  589. let inputStream = InputStream(data: Data("data".utf8))
  590. let endpoint = Endpoint.method(.post)
  591. let methodAdapter = HTTPMethodAdapter(method: .get)
  592. let headerAdapter = HeaderAdapter()
  593. let monitor = ClosureEventMonitor()
  594. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  595. // When
  596. let expectation1 = expectation(description: "Request 1 created")
  597. monitor.requestDidCreateTask = { _, _ in expectation1.fulfill() }
  598. let request1 = session.upload(inputStream, to: endpoint)
  599. waitForExpectations(timeout: timeout)
  600. let expectation2 = expectation(description: "Request 2 created")
  601. monitor.requestDidCreateTask = { _, _ in expectation2.fulfill() }
  602. let request2 = session.upload(inputStream, to: endpoint, interceptor: headerAdapter)
  603. waitForExpectations(timeout: timeout)
  604. // Then
  605. XCTAssertEqual(request1.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  606. XCTAssertEqual(request2.task?.originalRequest?.httpMethod, methodAdapter.method.rawValue)
  607. XCTAssertEqual(request2.task?.originalRequest?.allHTTPHeaderFields?.count, 1)
  608. XCTAssertEqual(methodAdapter.adaptedCount, 2)
  609. XCTAssertEqual(headerAdapter.adaptedCount, 1)
  610. }
  611. func testThatSessionReturnsRequestAdaptationErrorWhenRequestAdapterThrowsError() {
  612. // Given
  613. let endpoint = Endpoint()
  614. let methodAdapter = HTTPMethodAdapter(method: .post, throwsError: true)
  615. let headerAdapter = HeaderAdapter(throwsError: true)
  616. let monitor = ClosureEventMonitor()
  617. let session = Session(startRequestsImmediately: false, interceptor: methodAdapter, eventMonitors: [monitor])
  618. // When
  619. let expectation1 = expectation(description: "Request 1 created")
  620. monitor.requestDidFailToAdaptURLRequestWithError = { _, _, _ in expectation1.fulfill() }
  621. let request1 = session.request(endpoint)
  622. waitForExpectations(timeout: timeout)
  623. let expectation2 = expectation(description: "Request 2 created")
  624. monitor.requestDidFailToAdaptURLRequestWithError = { _, _, _ in expectation2.fulfill() }
  625. let request2 = session.request(endpoint, interceptor: headerAdapter)
  626. waitForExpectations(timeout: timeout)
  627. let requests = [request1, request2]
  628. // Then
  629. for request in requests {
  630. XCTAssertEqual(request.error?.isRequestAdaptationError, true)
  631. XCTAssertEqual(request.error?.underlyingError?.asAFError?.urlConvertible as? String, "")
  632. }
  633. }
  634. // MARK: Tests - Request Retrier
  635. func testThatSessionCallsRequestRetrierWhenRequestInitiallyEncountersAdaptError() {
  636. // Given
  637. let handler = RequestHandler()
  638. handler.adaptedCount = 1
  639. handler.throwsErrorOnSecondAdapt = true
  640. handler.shouldApplyAuthorizationHeader = true
  641. let session = Session()
  642. let expectation = self.expectation(description: "request should eventually fail")
  643. var response: DataResponse<TestResponse, AFError>?
  644. // When
  645. session.request(.basicAuth(), interceptor: handler)
  646. .validate()
  647. .responseDecodable(of: TestResponse.self) { jsonResponse in
  648. response = jsonResponse
  649. expectation.fulfill()
  650. }
  651. waitForExpectations(timeout: timeout)
  652. // Then
  653. XCTAssertEqual(handler.adaptCalledCount, 2)
  654. XCTAssertEqual(handler.adaptedCount, 2)
  655. XCTAssertEqual(handler.retryCalledCount, 1)
  656. XCTAssertEqual(handler.retryCount, 1)
  657. XCTAssertEqual(response?.result.isSuccess, true)
  658. assert(on: session.rootQueue) {
  659. XCTAssertTrue(session.requestTaskMap.isEmpty)
  660. XCTAssertTrue(session.activeRequests.isEmpty)
  661. }
  662. }
  663. func testThatSessionCallsRequestRetrierWhenDownloadInitiallyEncountersAdaptError() {
  664. // Given
  665. let handler = RequestHandler()
  666. handler.adaptedCount = 1
  667. handler.throwsErrorOnSecondAdapt = true
  668. handler.shouldApplyAuthorizationHeader = true
  669. let session = Session()
  670. let expectation = self.expectation(description: "request should eventually fail")
  671. var response: DownloadResponse<TestResponse, AFError>?
  672. let destination: DownloadRequest.Destination = { _, _ in
  673. let fileURL = self.testDirectoryURL.appendingPathComponent("test-output.json")
  674. return (fileURL, [.removePreviousFile])
  675. }
  676. // When
  677. session.download(.basicAuth(), interceptor: handler, to: destination)
  678. .validate()
  679. .responseDecodable(of: TestResponse.self) { jsonResponse in
  680. response = jsonResponse
  681. expectation.fulfill()
  682. }
  683. waitForExpectations(timeout: timeout)
  684. // Then
  685. XCTAssertEqual(handler.adaptCalledCount, 2)
  686. XCTAssertEqual(handler.adaptedCount, 2)
  687. XCTAssertEqual(handler.retryCalledCount, 1)
  688. XCTAssertEqual(handler.retryCount, 1)
  689. XCTAssertEqual(response?.result.isSuccess, true)
  690. assert(on: session.rootQueue) {
  691. XCTAssertTrue(session.requestTaskMap.isEmpty)
  692. XCTAssertTrue(session.activeRequests.isEmpty)
  693. }
  694. }
  695. func testThatSessionCallsRequestRetrierWhenUploadInitiallyEncountersAdaptError() {
  696. // Given
  697. let handler = UploadHandler()
  698. let session = Session(interceptor: handler)
  699. let expectation = self.expectation(description: "request should eventually fail")
  700. var response: DataResponse<TestResponse, AFError>?
  701. let uploadData = Data("upload data".utf8)
  702. // When
  703. session.upload(uploadData, to: .method(.post))
  704. .validate()
  705. .responseDecodable(of: TestResponse.self) { jsonResponse in
  706. response = jsonResponse
  707. expectation.fulfill()
  708. }
  709. waitForExpectations(timeout: timeout)
  710. // Then
  711. XCTAssertEqual(handler.adaptCalledCount, 2)
  712. XCTAssertEqual(handler.adaptedCount, 2)
  713. XCTAssertEqual(handler.retryCalledCount, 1)
  714. XCTAssertEqual(handler.retryCount, 1)
  715. XCTAssertEqual(response?.result.isSuccess, true)
  716. assert(on: session.rootQueue) {
  717. XCTAssertTrue(session.requestTaskMap.isEmpty)
  718. XCTAssertTrue(session.activeRequests.isEmpty)
  719. }
  720. }
  721. func testThatSessionCallsRequestRetrierWhenRequestEncountersError() {
  722. // Given
  723. let handler = RequestHandler()
  724. let session = Session()
  725. let expectation = self.expectation(description: "request should eventually fail")
  726. var response: DataResponse<TestResponse, AFError>?
  727. // When
  728. let request = session.request(.basicAuth(), interceptor: handler)
  729. .validate()
  730. .responseDecodable(of: TestResponse.self) { jsonResponse in
  731. response = jsonResponse
  732. expectation.fulfill()
  733. }
  734. waitForExpectations(timeout: timeout)
  735. // Then
  736. XCTAssertEqual(handler.adaptCalledCount, 2)
  737. XCTAssertEqual(handler.adaptedCount, 2)
  738. XCTAssertEqual(handler.retryCalledCount, 3)
  739. XCTAssertEqual(handler.retryCount, 3)
  740. XCTAssertEqual(request.retryCount, 1)
  741. XCTAssertEqual(response?.result.isSuccess, false)
  742. assert(on: session.rootQueue) {
  743. XCTAssertTrue(session.requestTaskMap.isEmpty)
  744. XCTAssertTrue(session.activeRequests.isEmpty)
  745. }
  746. }
  747. func testThatSessionCallsRequestRetrierThenSessionRetrierWhenRequestEncountersError() {
  748. // Given
  749. let sessionHandler = RequestHandler()
  750. let requestHandler = RequestHandler()
  751. let session = Session(interceptor: sessionHandler)
  752. let expectation = self.expectation(description: "request should eventually fail")
  753. var response: DataResponse<TestResponse, AFError>?
  754. // When
  755. let request = session.request(.basicAuth(), interceptor: requestHandler)
  756. .validate()
  757. .responseDecodable(of: TestResponse.self) { jsonResponse in
  758. response = jsonResponse
  759. expectation.fulfill()
  760. }
  761. waitForExpectations(timeout: timeout)
  762. // Then
  763. XCTAssertEqual(sessionHandler.adaptCalledCount, 3)
  764. XCTAssertEqual(sessionHandler.adaptedCount, 3)
  765. XCTAssertEqual(sessionHandler.retryCalledCount, 3)
  766. XCTAssertEqual(sessionHandler.retryCount, 3)
  767. XCTAssertEqual(requestHandler.adaptCalledCount, 3)
  768. XCTAssertEqual(requestHandler.adaptedCount, 3)
  769. XCTAssertEqual(requestHandler.retryCalledCount, 4)
  770. XCTAssertEqual(requestHandler.retryCount, 4)
  771. XCTAssertEqual(request.retryCount, 2)
  772. XCTAssertEqual(response?.result.isSuccess, false)
  773. assert(on: session.rootQueue) {
  774. XCTAssertTrue(session.requestTaskMap.isEmpty)
  775. XCTAssertTrue(session.activeRequests.isEmpty)
  776. }
  777. }
  778. func testThatSessionCallsAdapterWhenRequestIsRetried() {
  779. // Given
  780. let handler = RequestHandler()
  781. handler.shouldApplyAuthorizationHeader = true
  782. let session = Session(interceptor: handler)
  783. let expectation = self.expectation(description: "request should eventually succeed")
  784. var response: DataResponse<TestResponse, AFError>?
  785. // When
  786. let request = session.request(.basicAuth())
  787. .validate()
  788. .responseDecodable(of: TestResponse.self) { jsonResponse in
  789. response = jsonResponse
  790. expectation.fulfill()
  791. }
  792. waitForExpectations(timeout: timeout)
  793. // Then
  794. XCTAssertEqual(handler.adaptCalledCount, 2)
  795. XCTAssertEqual(handler.adaptedCount, 2)
  796. XCTAssertEqual(handler.retryCalledCount, 1)
  797. XCTAssertEqual(handler.retryCount, 1)
  798. XCTAssertEqual(request.retryCount, 1)
  799. XCTAssertEqual(response?.result.isSuccess, true)
  800. assert(on: session.rootQueue) {
  801. XCTAssertTrue(session.requestTaskMap.isEmpty)
  802. XCTAssertTrue(session.activeRequests.isEmpty)
  803. }
  804. }
  805. func testThatSessionReturnsRequestAdaptationErrorWhenRequestIsRetried() {
  806. // Given
  807. let handler = RequestHandler()
  808. handler.throwsErrorOnSecondAdapt = true
  809. let session = Session(interceptor: handler)
  810. let expectation = self.expectation(description: "request should eventually fail")
  811. var response: DataResponse<TestResponse, AFError>?
  812. // When
  813. let request = session.request(.basicAuth())
  814. .validate()
  815. .responseDecodable(of: TestResponse.self) { jsonResponse in
  816. response = jsonResponse
  817. expectation.fulfill()
  818. }
  819. waitForExpectations(timeout: timeout)
  820. // Then
  821. XCTAssertEqual(handler.adaptCalledCount, 2)
  822. XCTAssertEqual(handler.adaptedCount, 1)
  823. XCTAssertEqual(handler.retryCalledCount, 3)
  824. XCTAssertEqual(handler.retryCount, 3)
  825. XCTAssertEqual(request.retryCount, 1)
  826. XCTAssertEqual(response?.result.isSuccess, false)
  827. XCTAssertEqual(request.error?.isRequestAdaptationError, true)
  828. XCTAssertEqual(request.error?.underlyingError?.asAFError?.urlConvertible as? String, "/adapt/error/2")
  829. assert(on: session.rootQueue) {
  830. XCTAssertTrue(session.requestTaskMap.isEmpty)
  831. XCTAssertTrue(session.activeRequests.isEmpty)
  832. }
  833. }
  834. func testThatSessionRetriesRequestWithDelayWhenRetryResultContainsDelay() {
  835. // Given
  836. let handler = RequestHandler()
  837. handler.retryDelay = 0.01
  838. handler.throwsErrorOnSecondAdapt = true
  839. let session = Session(interceptor: handler)
  840. let expectation = self.expectation(description: "request should eventually fail")
  841. var response: DataResponse<TestResponse, AFError>?
  842. // When
  843. let request = session.request(.basicAuth())
  844. .validate()
  845. .responseDecodable(of: TestResponse.self) { jsonResponse in
  846. response = jsonResponse
  847. expectation.fulfill()
  848. }
  849. waitForExpectations(timeout: timeout)
  850. // Then
  851. XCTAssertEqual(handler.adaptCalledCount, 2)
  852. XCTAssertEqual(handler.adaptedCount, 1)
  853. XCTAssertEqual(handler.retryCalledCount, 3)
  854. XCTAssertEqual(handler.retryCount, 3)
  855. XCTAssertEqual(request.retryCount, 1)
  856. XCTAssertEqual(response?.result.isSuccess, false)
  857. XCTAssertEqual(request.error?.isRequestAdaptationError, true)
  858. XCTAssertEqual(request.error?.underlyingError?.asAFError?.urlConvertible as? String, "/adapt/error/2")
  859. assert(on: session.rootQueue) {
  860. XCTAssertTrue(session.requestTaskMap.isEmpty)
  861. XCTAssertTrue(session.activeRequests.isEmpty)
  862. }
  863. }
  864. func testThatSessionReturnsRequestRetryErrorWhenRequestRetrierThrowsError() {
  865. // Given
  866. let handler = RequestHandler()
  867. handler.throwsErrorOnRetry = true
  868. let session = Session(interceptor: handler)
  869. let expectation = self.expectation(description: "request should eventually fail")
  870. var response: DataResponse<TestResponse, AFError>?
  871. // When
  872. let request = session.request(.basicAuth())
  873. .validate()
  874. .responseDecodable(of: TestResponse.self) { jsonResponse in
  875. response = jsonResponse
  876. expectation.fulfill()
  877. }
  878. waitForExpectations(timeout: timeout)
  879. // Then
  880. XCTAssertEqual(handler.adaptCalledCount, 1)
  881. XCTAssertEqual(handler.adaptedCount, 1)
  882. XCTAssertEqual(handler.retryCalledCount, 2)
  883. XCTAssertEqual(handler.retryCount, 0)
  884. XCTAssertEqual(request.retryCount, 0)
  885. XCTAssertEqual(response?.result.isSuccess, false)
  886. assert(on: session.rootQueue) {
  887. XCTAssertTrue(session.requestTaskMap.isEmpty)
  888. XCTAssertTrue(session.activeRequests.isEmpty)
  889. }
  890. if let error = response?.result.failure {
  891. XCTAssertTrue(error.isRequestRetryError)
  892. XCTAssertEqual(error.underlyingError?.asAFError?.urlConvertible as? String, "/invalid/url/2")
  893. } else {
  894. XCTFail("error should not be nil")
  895. }
  896. }
  897. // MARK: Tests - Response Serializer Retry
  898. func testThatSessionCallsRequestRetrierWhenResponseSerializerThrowsError() {
  899. // Given
  900. let handler = RequestHandler()
  901. handler.shouldRetry = false
  902. let session = Session()
  903. let expectation = self.expectation(description: "request should eventually fail")
  904. var response: DataResponse<TestResponse, AFError>?
  905. // When
  906. let request = session.request(.image(.jpeg), interceptor: handler)
  907. .validate()
  908. .responseDecodable(of: TestResponse.self) { jsonResponse in
  909. response = jsonResponse
  910. expectation.fulfill()
  911. }
  912. waitForExpectations(timeout: timeout)
  913. // Then
  914. XCTAssertEqual(handler.adaptCalledCount, 1)
  915. XCTAssertEqual(handler.adaptedCount, 1)
  916. XCTAssertEqual(handler.retryCalledCount, 1)
  917. XCTAssertEqual(handler.retryCount, 0)
  918. XCTAssertEqual(request.retryCount, 0)
  919. XCTAssertEqual(response?.result.isSuccess, false)
  920. XCTAssertEqual(response?.error?.isResponseSerializationError, true)
  921. XCTAssertNotNil(response?.error?.underlyingError as? DecodingError)
  922. assert(on: session.rootQueue) {
  923. XCTAssertTrue(session.requestTaskMap.isEmpty)
  924. XCTAssertTrue(session.activeRequests.isEmpty)
  925. }
  926. }
  927. func testThatSessionCallsRequestRetrierForAllResponseSerializersThatThrowError() throws {
  928. // Given
  929. let handler = RequestHandler()
  930. handler.throwsErrorOnRetry = true
  931. let session = Session()
  932. let json1Expectation = expectation(description: "request should eventually fail")
  933. var json1Response: DataResponse<TestResponse, AFError>?
  934. let json2Expectation = expectation(description: "request should eventually fail")
  935. var json2Response: DataResponse<TestResponse, AFError>?
  936. // When
  937. let request = session.request(.image(.jpeg), interceptor: handler)
  938. .validate()
  939. .responseDecodable(of: TestResponse.self) { response in
  940. json1Response = response
  941. json1Expectation.fulfill()
  942. }
  943. .responseDecodable(of: TestResponse.self) { response in
  944. json2Response = response
  945. json2Expectation.fulfill()
  946. }
  947. waitForExpectations(timeout: timeout)
  948. // Then
  949. XCTAssertEqual(handler.adaptCalledCount, 1)
  950. XCTAssertEqual(handler.adaptedCount, 1)
  951. XCTAssertEqual(handler.retryCalledCount, 2)
  952. XCTAssertEqual(handler.retryCount, 0)
  953. XCTAssertEqual(request.retryCount, 0)
  954. XCTAssertEqual(json1Response?.result.isSuccess, false)
  955. XCTAssertEqual(json2Response?.result.isSuccess, false)
  956. assert(on: session.rootQueue) {
  957. XCTAssertTrue(session.requestTaskMap.isEmpty)
  958. XCTAssertTrue(session.activeRequests.isEmpty)
  959. }
  960. let errors = [json1Response, json2Response].compactMap { $0?.error }
  961. XCTAssertEqual(errors.count, 2)
  962. for (index, error) in errors.enumerated() {
  963. XCTAssertTrue(error.isRequestRetryError)
  964. if case let .requestRetryFailed(retryError, originalError) = error {
  965. XCTAssertEqual(retryError.asAFError?.urlConvertible as? String, "/invalid/url/\(index + 1)")
  966. XCTAssertNotNil(originalError.asAFError?.underlyingError as? DecodingError)
  967. } else {
  968. XCTFail("Error failure reason should be response serialization failure")
  969. }
  970. }
  971. }
  972. func testThatSessionRetriesRequestImmediatelyWhenResponseSerializerRequestsRetry() throws {
  973. // Given
  974. let handler = RequestHandler()
  975. let session = Session()
  976. let json1Expectation = expectation(description: "request should eventually fail")
  977. var json1Response: DataResponse<TestResponse, AFError>?
  978. let json2Expectation = expectation(description: "request should eventually fail")
  979. var json2Response: DataResponse<TestResponse, AFError>?
  980. // When
  981. let request = session.request(.image(.jpeg), interceptor: handler)
  982. .validate()
  983. .responseDecodable(of: TestResponse.self) { response in
  984. json1Response = response
  985. json1Expectation.fulfill()
  986. }
  987. .responseDecodable(of: TestResponse.self) { response in
  988. json2Response = response
  989. json2Expectation.fulfill()
  990. }
  991. waitForExpectations(timeout: timeout)
  992. // Then
  993. XCTAssertEqual(handler.adaptCalledCount, 2)
  994. XCTAssertEqual(handler.adaptedCount, 2)
  995. XCTAssertEqual(handler.retryCalledCount, 3)
  996. XCTAssertEqual(handler.retryCount, 3)
  997. XCTAssertEqual(request.retryCount, 1)
  998. XCTAssertEqual(json1Response?.result.isSuccess, false)
  999. XCTAssertEqual(json2Response?.result.isSuccess, false)
  1000. assert(on: session.rootQueue) {
  1001. XCTAssertTrue(session.requestTaskMap.isEmpty)
  1002. XCTAssertTrue(session.activeRequests.isEmpty)
  1003. }
  1004. let errors = [json1Response, json2Response].compactMap { $0?.error }
  1005. XCTAssertEqual(errors.count, 2)
  1006. for error in errors {
  1007. XCTAssertTrue(error.isResponseSerializationError)
  1008. XCTAssertNotNil(error.underlyingError as? DecodingError)
  1009. }
  1010. }
  1011. func testThatSessionCallsResponseSerializerCompletionsWhenAdapterThrowsErrorDuringRetry() {
  1012. // Four retries should occur given this scenario:
  1013. // 1) Retrier is called from first response serializer failure (trips retry)
  1014. // 2) Retrier is called by Session for adapt error thrown
  1015. // 3) Retrier is called again from first response serializer failure
  1016. // 4) Retrier is called from second response serializer failure
  1017. // Given
  1018. let handler = RequestHandler()
  1019. handler.throwsErrorOnSecondAdapt = true
  1020. let session = Session()
  1021. let json1Expectation = expectation(description: "request should eventually fail")
  1022. var json1Response: DataResponse<TestResponse, AFError>?
  1023. let json2Expectation = expectation(description: "request should eventually fail")
  1024. var json2Response: DataResponse<TestResponse, AFError>?
  1025. // When
  1026. let request = session.request(.image(.jpeg), interceptor: handler)
  1027. .validate()
  1028. .responseDecodable(of: TestResponse.self) { response in
  1029. json1Response = response
  1030. json1Expectation.fulfill()
  1031. }
  1032. .responseDecodable(of: TestResponse.self) { response in
  1033. json2Response = response
  1034. json2Expectation.fulfill()
  1035. }
  1036. waitForExpectations(timeout: timeout)
  1037. // Then
  1038. XCTAssertEqual(handler.adaptCalledCount, 2)
  1039. XCTAssertEqual(handler.adaptedCount, 1)
  1040. XCTAssertEqual(handler.retryCalledCount, 4)
  1041. XCTAssertEqual(handler.retryCount, 4)
  1042. XCTAssertEqual(request.retryCount, 1)
  1043. XCTAssertEqual(json1Response?.result.isSuccess, false)
  1044. XCTAssertEqual(json2Response?.result.isSuccess, false)
  1045. assert(on: session.rootQueue) {
  1046. XCTAssertTrue(session.requestTaskMap.isEmpty)
  1047. XCTAssertTrue(session.activeRequests.isEmpty)
  1048. }
  1049. let errors = [json1Response, json2Response].compactMap { $0?.error }
  1050. XCTAssertEqual(errors.count, 2)
  1051. for error in errors {
  1052. XCTAssertTrue(error.isRequestAdaptationError)
  1053. XCTAssertEqual(error.underlyingError?.asAFError?.urlConvertible as? String, "/adapt/error/2")
  1054. }
  1055. }
  1056. func testThatSessionCallsResponseSerializerCompletionsWhenAdapterThrowsErrorDuringRetryForDownloads() {
  1057. // Four retries should occur given this scenario:
  1058. // 1) Retrier is called from first response serializer failure (trips retry)
  1059. // 2) Retrier is called by Session for adapt error thrown
  1060. // 3) Retrier is called again from first response serializer failure
  1061. // 4) Retrier is called from second response serializer failure
  1062. // Given
  1063. let handler = RequestHandler()
  1064. handler.throwsErrorOnSecondAdapt = true
  1065. let session = Session()
  1066. let json1Expectation = expectation(description: "request should eventually fail")
  1067. var json1Response: DownloadResponse<TestResponse, AFError>?
  1068. let json2Expectation = expectation(description: "request should eventually fail")
  1069. var json2Response: DownloadResponse<TestResponse, AFError>?
  1070. // When
  1071. let request = session.download(.image(.jpeg), interceptor: handler)
  1072. .validate()
  1073. .responseDecodable(of: TestResponse.self) { response in
  1074. json1Response = response
  1075. json1Expectation.fulfill()
  1076. }
  1077. .responseDecodable(of: TestResponse.self) { response in
  1078. json2Response = response
  1079. json2Expectation.fulfill()
  1080. }
  1081. waitForExpectations(timeout: timeout)
  1082. // Then
  1083. XCTAssertEqual(handler.adaptCalledCount, 2)
  1084. XCTAssertEqual(handler.adaptedCount, 1)
  1085. XCTAssertEqual(handler.retryCalledCount, 4)
  1086. XCTAssertEqual(handler.retryCount, 4)
  1087. XCTAssertEqual(request.retryCount, 1)
  1088. XCTAssertEqual(json1Response?.result.isSuccess, false)
  1089. XCTAssertEqual(json2Response?.result.isSuccess, false)
  1090. assert(on: session.rootQueue) {
  1091. XCTAssertTrue(session.requestTaskMap.isEmpty)
  1092. XCTAssertTrue(session.activeRequests.isEmpty)
  1093. }
  1094. let errors = [json1Response, json2Response].compactMap { $0?.error }
  1095. XCTAssertEqual(errors.count, 2)
  1096. for error in errors {
  1097. XCTAssertTrue(error.isRequestAdaptationError)
  1098. XCTAssertEqual(error.underlyingError?.asAFError?.urlConvertible as? String, "/adapt/error/2")
  1099. }
  1100. }
  1101. // MARK: Tests - Session Invalidation
  1102. func testThatSessionIsInvalidatedAndAllRequestsCompleteWhenSessionIsDeinitialized() {
  1103. // Given
  1104. let invalidationExpectation = expectation(description: "sessionDidBecomeInvalidWithError should be called")
  1105. let events = ClosureEventMonitor()
  1106. events.sessionDidBecomeInvalidWithError = { _, _ in
  1107. invalidationExpectation.fulfill()
  1108. }
  1109. var session: Session? = Session(startRequestsImmediately: false, eventMonitors: [events])
  1110. var error: AFError?
  1111. let requestExpectation = expectation(description: "request should complete")
  1112. // When
  1113. session?.request(.default).response { response in
  1114. error = response.error
  1115. requestExpectation.fulfill()
  1116. }
  1117. session = nil
  1118. waitForExpectations(timeout: timeout)
  1119. // Then
  1120. XCTAssertEqual(error?.isSessionDeinitializedError, true)
  1121. }
  1122. // MARK: Tests - Request Cancellation
  1123. func testThatSessionOnlyCallsResponseSerializerCompletionWhenCancellingInsideCompletion() {
  1124. // Given
  1125. let handler = RequestHandler()
  1126. let session = Session()
  1127. let expectation = self.expectation(description: "request should complete")
  1128. var response: DataResponse<TestResponse, AFError>?
  1129. var completionCallCount = 0
  1130. // When
  1131. let request = session.request(.default, interceptor: handler)
  1132. request.validate()
  1133. request.responseDecodable(of: TestResponse.self) { resp in
  1134. request.cancel()
  1135. response = resp
  1136. completionCallCount += 1
  1137. DispatchQueue.main.after(0.01) { expectation.fulfill() }
  1138. }
  1139. waitForExpectations(timeout: timeout)
  1140. // Then
  1141. XCTAssertEqual(handler.adaptCalledCount, 1)
  1142. XCTAssertEqual(handler.adaptedCount, 1)
  1143. XCTAssertEqual(handler.retryCalledCount, 0)
  1144. XCTAssertEqual(handler.retryCount, 0)
  1145. XCTAssertEqual(request.retryCount, 0)
  1146. XCTAssertEqual(response?.result.isSuccess, true)
  1147. XCTAssertEqual(completionCallCount, 1)
  1148. assert(on: session.rootQueue) {
  1149. XCTAssertTrue(session.requestTaskMap.isEmpty)
  1150. XCTAssertTrue(session.activeRequests.isEmpty)
  1151. }
  1152. }
  1153. // MARK: Tests - Request State
  1154. func testThatSessionSetsRequestStateWhenStartRequestsImmediatelyIsTrue() {
  1155. // Given
  1156. let session = Session()
  1157. let expectation = self.expectation(description: "request should complete")
  1158. var response: DataResponse<TestResponse, AFError>?
  1159. // When
  1160. let request = session.request(.default).responseDecodable(of: TestResponse.self) { resp in
  1161. response = resp
  1162. expectation.fulfill()
  1163. }
  1164. waitForExpectations(timeout: timeout)
  1165. // Then
  1166. XCTAssertEqual(request.state, .finished)
  1167. XCTAssertEqual(response?.result.isSuccess, true)
  1168. }
  1169. // MARK: Invalid Requests
  1170. func testThatGETRequestsWithBodyDataAreConsideredInvalid() {
  1171. // Given
  1172. let session = Session()
  1173. var request = Endpoint().urlRequest
  1174. request.httpBody = Data("invalid".utf8)
  1175. let expect = expectation(description: "request should complete")
  1176. var response: DataResponse<TestResponse, AFError>?
  1177. // When
  1178. session.request(request).responseDecodable(of: TestResponse.self) { resp in
  1179. response = resp
  1180. expect.fulfill()
  1181. }
  1182. waitForExpectations(timeout: timeout)
  1183. // Then
  1184. XCTAssertEqual(response?.result.isFailure, true)
  1185. XCTAssertEqual(response?.error?.isBodyDataInGETRequest, true)
  1186. }
  1187. func testThatAdaptedGETRequestsWithBodyDataAreConsideredInvalid() {
  1188. // Given
  1189. struct InvalidAdapter: RequestInterceptor {
  1190. func adapt(_ urlRequest: URLRequest,
  1191. for session: Session,
  1192. completion: @escaping (Result<URLRequest, Error>) -> Void) {
  1193. var request = urlRequest
  1194. request.httpBody = Data("invalid".utf8)
  1195. completion(.success(request))
  1196. }
  1197. }
  1198. let session = Session(interceptor: InvalidAdapter())
  1199. let expect = expectation(description: "request should complete")
  1200. var response: DataResponse<TestResponse, AFError>?
  1201. // When
  1202. session.request(.default).responseDecodable(of: TestResponse.self) { resp in
  1203. response = resp
  1204. expect.fulfill()
  1205. }
  1206. waitForExpectations(timeout: timeout)
  1207. // Then
  1208. XCTAssertEqual(response?.result.isFailure, true)
  1209. XCTAssertEqual(response?.error?.isRequestAdaptationError, true)
  1210. XCTAssertEqual(response?.error?.underlyingError?.asAFError?.isBodyDataInGETRequest, true)
  1211. }
  1212. }
  1213. // MARK: -
  1214. final class SessionMassActionTestCase: BaseTestCase {
  1215. func testThatRequestsCanHaveMassActionsPerformed() {
  1216. // Given
  1217. let count = 10
  1218. let createdTasks = expectation(description: "all tasks created")
  1219. createdTasks.expectedFulfillmentCount = count
  1220. let massActions = expectation(description: "cancel all requests should be called")
  1221. let monitor = ClosureEventMonitor()
  1222. monitor.requestDidCreateTask = { _, _ in createdTasks.fulfill() }
  1223. let session = Session(eventMonitors: [monitor])
  1224. let request = Endpoint.delay(1)
  1225. var requests: [DataRequest] = []
  1226. // When
  1227. requests = (0..<count).map { _ in session.request(request) }
  1228. wait(for: [createdTasks], timeout: timeout)
  1229. session.withAllRequests { $0.forEach { $0.suspend() }; massActions.fulfill() }
  1230. wait(for: [massActions], timeout: timeout)
  1231. // Then
  1232. XCTAssertTrue(requests.allSatisfy { $0.isSuspended })
  1233. }
  1234. func testThatAutomaticallyResumedRequestsCanBeMassCancelled() {
  1235. // Given
  1236. let count = 100
  1237. let completion = expectation(description: "all requests should finish")
  1238. completion.expectedFulfillmentCount = count
  1239. let createdTasks = expectation(description: "all tasks created")
  1240. createdTasks.expectedFulfillmentCount = count
  1241. let gatheredMetrics = expectation(description: "metrics gathered for all tasks")
  1242. gatheredMetrics.expectedFulfillmentCount = count
  1243. let cancellation = expectation(description: "cancel all requests should be called")
  1244. let monitor = ClosureEventMonitor()
  1245. monitor.requestDidCreateTask = { _, _ in createdTasks.fulfill() }
  1246. monitor.requestDidGatherMetrics = { _, _ in gatheredMetrics.fulfill() }
  1247. let session = Session(eventMonitors: [monitor])
  1248. let request = Endpoint.delay(1)
  1249. var requests: [DataRequest] = []
  1250. var responses: [DataResponse<Data?, AFError>] = []
  1251. // When
  1252. requests = (0..<count).map { _ in session.request(request) }
  1253. wait(for: [createdTasks], timeout: timeout)
  1254. requests.forEach { request in
  1255. request.response { response in
  1256. responses.append(response)
  1257. completion.fulfill()
  1258. }
  1259. }
  1260. session.cancelAllRequests {
  1261. cancellation.fulfill()
  1262. }
  1263. wait(for: [gatheredMetrics, cancellation, completion], timeout: timeout)
  1264. // Then
  1265. XCTAssertTrue(responses.allSatisfy { $0.error?.isExplicitlyCancelledError == true })
  1266. assert(on: session.rootQueue) {
  1267. XCTAssertTrue(session.requestTaskMap.isEmpty, "requestTaskMap should be empty but has \(session.requestTaskMap.count) items")
  1268. XCTAssertTrue(session.activeRequests.isEmpty, "activeRequests should be empty but has \(session.activeRequests.count) items")
  1269. }
  1270. }
  1271. func testThatManuallyResumedRequestsCanBeMassCancelled() {
  1272. // Given
  1273. let count = 100
  1274. let completion = expectation(description: "all requests should finish")
  1275. completion.expectedFulfillmentCount = count
  1276. let createdTasks = expectation(description: "all tasks created")
  1277. createdTasks.expectedFulfillmentCount = count
  1278. let gatheredMetrics = expectation(description: "metrics gathered for all tasks")
  1279. gatheredMetrics.expectedFulfillmentCount = count
  1280. let cancellation = expectation(description: "cancel all requests should be called")
  1281. let monitor = ClosureEventMonitor()
  1282. monitor.requestDidCreateTask = { _, _ in createdTasks.fulfill() }
  1283. monitor.requestDidGatherMetrics = { _, _ in gatheredMetrics.fulfill() }
  1284. let session = Session(startRequestsImmediately: false, eventMonitors: [monitor])
  1285. let request = Endpoint.delay(1)
  1286. var responses: [DataResponse<Data?, AFError>] = []
  1287. // When
  1288. for _ in 0..<count {
  1289. session.request(request).response { response in
  1290. responses.append(response)
  1291. completion.fulfill()
  1292. }
  1293. }
  1294. wait(for: [createdTasks], timeout: timeout)
  1295. session.cancelAllRequests {
  1296. cancellation.fulfill()
  1297. }
  1298. wait(for: [gatheredMetrics, cancellation, completion], timeout: timeout)
  1299. // Then
  1300. XCTAssertTrue(responses.allSatisfy { $0.error?.isExplicitlyCancelledError == true })
  1301. assert(on: session.rootQueue) {
  1302. XCTAssertTrue(session.requestTaskMap.isEmpty, "requestTaskMap should be empty but has \(session.requestTaskMap.count) items")
  1303. XCTAssertTrue(session.activeRequests.isEmpty, "activeRequests should be empty but has \(session.activeRequests.count) items")
  1304. }
  1305. }
  1306. func testThatRetriedRequestsCanBeMassCancelled() {
  1307. // Given
  1308. final class OnceRetrier: RequestInterceptor {
  1309. private var hasRetried = false
  1310. func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
  1311. if hasRetried {
  1312. var request = urlRequest
  1313. request.url = Endpoint.delay(1).url
  1314. completion(.success(request))
  1315. } else {
  1316. completion(.success(urlRequest))
  1317. }
  1318. }
  1319. func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
  1320. completion(hasRetried ? .doNotRetry : .retry)
  1321. hasRetried = true
  1322. }
  1323. }
  1324. let queue = DispatchQueue(label: "com.alamofire.testQueue")
  1325. let monitor = ClosureEventMonitor(queue: queue)
  1326. let session = Session(rootQueue: queue, interceptor: OnceRetrier(), eventMonitors: [monitor])
  1327. let request = Endpoint.status(401)
  1328. let completion = expectation(description: "all requests should finish")
  1329. let cancellation = expectation(description: "cancel all requests should be called")
  1330. let createTask = expectation(description: "should create task twice")
  1331. createTask.expectedFulfillmentCount = 2
  1332. var tasksCreated = 0
  1333. monitor.requestDidCreateTask = { [unowned session] _, _ in
  1334. tasksCreated += 1
  1335. createTask.fulfill()
  1336. // Cancel after the second task is created to ensure proper lifetime events.
  1337. if tasksCreated == 2 {
  1338. session.cancelAllRequests {
  1339. cancellation.fulfill()
  1340. }
  1341. }
  1342. }
  1343. var received: DataResponse<Data?, AFError>?
  1344. // When
  1345. session.request(request).validate().response { response in
  1346. received = response
  1347. completion.fulfill()
  1348. }
  1349. waitForExpectations(timeout: timeout)
  1350. // Then
  1351. XCTAssertEqual(received?.error?.isExplicitlyCancelledError, true)
  1352. assert(on: session.rootQueue) {
  1353. XCTAssertTrue(session.requestTaskMap.isEmpty, "requestTaskMap should be empty but has \(session.requestTaskMap.count) items")
  1354. XCTAssertTrue(session.activeRequests.isEmpty, "activeRequests should be empty but has \(session.activeRequests.count) items")
  1355. }
  1356. }
  1357. }
  1358. // MARK: -
  1359. final class SessionConfigurationHeadersTestCase: BaseTestCase {
  1360. enum ConfigurationType {
  1361. case `default`, ephemeral
  1362. }
  1363. func testThatDefaultConfigurationHeadersAreSentWithRequest() {
  1364. // Given, When, Then
  1365. executeAuthorizationHeaderTest(for: .default)
  1366. }
  1367. func testThatEphemeralConfigurationHeadersAreSentWithRequest() {
  1368. // Given, When, Then
  1369. executeAuthorizationHeaderTest(for: .ephemeral)
  1370. }
  1371. private func executeAuthorizationHeaderTest(for type: ConfigurationType) {
  1372. // Given
  1373. let session: Session = {
  1374. let configuration: URLSessionConfiguration = {
  1375. let configuration: URLSessionConfiguration
  1376. switch type {
  1377. case .default:
  1378. configuration = .default
  1379. case .ephemeral:
  1380. configuration = .ephemeral
  1381. }
  1382. var headers = HTTPHeaders.default
  1383. headers["Authorization"] = "Bearer 123456"
  1384. configuration.headers = headers
  1385. return configuration
  1386. }()
  1387. return Session(configuration: configuration)
  1388. }()
  1389. let expectation = self.expectation(description: "request should complete successfully")
  1390. var response: DataResponse<TestResponse, AFError>?
  1391. // When
  1392. session.request(.default)
  1393. .responseDecodable(of: TestResponse.self) { closureResponse in
  1394. response = closureResponse
  1395. expectation.fulfill()
  1396. }
  1397. waitForExpectations(timeout: timeout)
  1398. // Then
  1399. XCTAssertNotNil(response?.request, "request should not be nil")
  1400. XCTAssertNotNil(response?.response, "response should not be nil")
  1401. XCTAssertNotNil(response?.data, "data should not be nil")
  1402. XCTAssertEqual(response?.result.isSuccess, true)
  1403. XCTAssertEqual(response?.value?.headers["Authorization"], "Bearer 123456", "Authorization header should match")
  1404. }
  1405. }