SessionTests.swift 65 KB

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