SessionTests.swift 66 KB

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