SessionTests.swift 66 KB

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