RequestTests.swift 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893
  1. //
  2. // RequestTests.swift
  3. //
  4. // Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. import Alamofire
  25. import Foundation
  26. import Testing
  27. import XCTest
  28. final class RequestResponseTestCase: BaseTestCase {
  29. @MainActor
  30. func testRequestResponse() {
  31. // Given
  32. let url = Endpoint.get.url
  33. let expectation = expectation(description: "GET request should succeed: \(url)")
  34. var response: DataResponse<Data?, AFError>?
  35. // When
  36. AF.request(url, parameters: ["foo": "bar"])
  37. .response { resp in
  38. response = resp
  39. expectation.fulfill()
  40. }
  41. waitForExpectations(timeout: timeout)
  42. // Then
  43. XCTAssertNotNil(response?.request)
  44. XCTAssertNotNil(response?.response)
  45. XCTAssertNotNil(response?.data)
  46. XCTAssertNil(response?.error)
  47. }
  48. @MainActor
  49. func testThatDataRequestReceivesInitialResponse() {
  50. // Given
  51. let url = Endpoint.get.url
  52. var initialResponse: HTTPURLResponse?
  53. let didReceiveResponse = expectation(description: "didReceiveResponse")
  54. let didComplete = expectation(description: "GET request should succeed: \(url)")
  55. var response: DataResponse<Data?, AFError>?
  56. // When
  57. AF.request(url, parameters: ["foo": "bar"])
  58. .onHTTPResponse { response in
  59. initialResponse = response
  60. didReceiveResponse.fulfill()
  61. }
  62. .response { resp in
  63. response = resp
  64. didComplete.fulfill()
  65. }
  66. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  67. // Then
  68. XCTAssertEqual(initialResponse, response?.response)
  69. XCTAssertNotNil(response?.request)
  70. XCTAssertNotNil(response?.response)
  71. XCTAssertNotNil(response?.data)
  72. XCTAssertNil(response?.error)
  73. }
  74. @MainActor
  75. func testThatDataRequestOnHTTPResponseCanAllow() {
  76. // Given
  77. let url = Endpoint.get.url
  78. var initialResponse: HTTPURLResponse?
  79. let didReceiveResponse = expectation(description: "didReceiveResponse")
  80. let didComplete = expectation(description: "GET request should succeed: \(url)")
  81. var response: DataResponse<Data?, AFError>?
  82. // When
  83. AF.request(url, parameters: ["foo": "bar"])
  84. .onHTTPResponse { response, completionHandler in
  85. initialResponse = response
  86. didReceiveResponse.fulfill()
  87. completionHandler(.allow)
  88. }
  89. .response { resp in
  90. response = resp
  91. didComplete.fulfill()
  92. }
  93. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  94. // Then
  95. XCTAssertEqual(initialResponse, response?.response)
  96. XCTAssertNotNil(response?.request)
  97. XCTAssertNotNil(response?.response)
  98. XCTAssertNotNil(response?.data)
  99. XCTAssertNil(response?.error)
  100. }
  101. @MainActor
  102. func testThatDataRequestOnHTTPResponseCanCancel() {
  103. // Given
  104. let url = Endpoint.get.url
  105. var initialResponse: HTTPURLResponse?
  106. let didReceiveResponse = expectation(description: "didReceiveResponse")
  107. let didComplete = expectation(description: "GET request should succeed: \(url)")
  108. var response: DataResponse<Data?, AFError>?
  109. // When
  110. let request = AF.request(url, parameters: ["foo": "bar"])
  111. .onHTTPResponse { response, completionHandler in
  112. initialResponse = response
  113. didReceiveResponse.fulfill()
  114. completionHandler(.cancel)
  115. }
  116. .response { resp in
  117. response = resp
  118. didComplete.fulfill()
  119. }
  120. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  121. // Then
  122. XCTAssertEqual(initialResponse, response?.response)
  123. XCTAssertNotNil(response?.request)
  124. XCTAssertNotNil(response?.response)
  125. XCTAssertNil(response?.data)
  126. XCTAssertTrue(request.isCancelled, "onHTTPResponse cancelled request should have isCancelled == true")
  127. XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true, "onHTTPResponse cancelled request should be explicitly cancelled")
  128. }
  129. @MainActor
  130. func testRequestResponseWithProgress() {
  131. // Given
  132. let byteCount = 512
  133. let url = Endpoint.bytes(byteCount).url
  134. let expectation = expectation(description: "Bytes download progress should be reported: \(url)")
  135. var progressValues: [Double] = []
  136. var response: DataResponse<Data?, AFError>?
  137. // When
  138. AF.request(url)
  139. .downloadProgress { progress in
  140. progressValues.append(progress.fractionCompleted)
  141. }
  142. .response { resp in
  143. response = resp
  144. expectation.fulfill()
  145. }
  146. waitForExpectations(timeout: timeout)
  147. // Then
  148. XCTAssertNotNil(response?.request)
  149. XCTAssertNotNil(response?.response)
  150. XCTAssertNotNil(response?.data)
  151. XCTAssertNil(response?.error)
  152. var previousProgress: Double = progressValues.first ?? 0.0
  153. for progress in progressValues {
  154. XCTAssertGreaterThanOrEqual(progress, previousProgress)
  155. previousProgress = progress
  156. }
  157. if let lastProgressValue = progressValues.last {
  158. XCTAssertEqual(lastProgressValue, 1.0)
  159. } else {
  160. XCTFail("last item in progressValues should not be nil")
  161. }
  162. }
  163. @MainActor
  164. func testPOSTRequestWithUnicodeParameters() {
  165. // Given
  166. let parameters = ["french": "français",
  167. "japanese": "日本語",
  168. "arabic": "العربية",
  169. "emoji": "😃"]
  170. let expectation = expectation(description: "request should succeed")
  171. var response: DataResponse<TestResponse, AFError>?
  172. // When
  173. AF.request(.method(.post), parameters: parameters)
  174. .responseDecodable(of: TestResponse.self) { closureResponse in
  175. response = closureResponse
  176. expectation.fulfill()
  177. }
  178. waitForExpectations(timeout: timeout)
  179. // Then
  180. XCTAssertNotNil(response?.request)
  181. XCTAssertNotNil(response?.response)
  182. XCTAssertNotNil(response?.data)
  183. if let form = response?.result.success?.form {
  184. XCTAssertEqual(form["french"], parameters["french"])
  185. XCTAssertEqual(form["japanese"], parameters["japanese"])
  186. XCTAssertEqual(form["arabic"], parameters["arabic"])
  187. XCTAssertEqual(form["emoji"], parameters["emoji"])
  188. } else {
  189. XCTFail("form parameter in JSON should not be nil")
  190. }
  191. }
  192. @MainActor
  193. func testPOSTRequestWithBase64EncodedImages() {
  194. // Given
  195. let pngBase64EncodedString: String = {
  196. let fileURL = url(forResource: "unicorn", withExtension: "png")
  197. let data = try! Data(contentsOf: fileURL)
  198. return data.base64EncodedString(options: .lineLength64Characters)
  199. }()
  200. let jpegBase64EncodedString: String = {
  201. let fileURL = url(forResource: "rainbow", withExtension: "jpg")
  202. let data = try! Data(contentsOf: fileURL)
  203. return data.base64EncodedString(options: .lineLength64Characters)
  204. }()
  205. let parameters = ["email": "user@alamofire.org",
  206. "png_image": pngBase64EncodedString,
  207. "jpeg_image": jpegBase64EncodedString]
  208. let expectation = expectation(description: "request should succeed")
  209. var response: DataResponse<TestResponse, AFError>?
  210. // When
  211. AF.request(Endpoint.method(.post), method: .post, parameters: parameters)
  212. .responseDecodable(of: TestResponse.self) { closureResponse in
  213. response = closureResponse
  214. expectation.fulfill()
  215. }
  216. waitForExpectations(timeout: timeout)
  217. // Then
  218. XCTAssertNotNil(response?.request)
  219. XCTAssertNotNil(response?.response)
  220. XCTAssertNotNil(response?.data)
  221. XCTAssertEqual(response?.result.isSuccess, true)
  222. if let form = response?.result.success?.form {
  223. XCTAssertEqual(form["email"], parameters["email"])
  224. XCTAssertEqual(form["png_image"], parameters["png_image"])
  225. XCTAssertEqual(form["jpeg_image"], parameters["jpeg_image"])
  226. } else {
  227. XCTFail("form parameter in JSON should not be nil")
  228. }
  229. }
  230. // MARK: Queues
  231. @MainActor
  232. func testThatResponseSerializationWorksWithSerializationQueue() {
  233. // Given
  234. let queue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  235. let manager = Session(serializationQueue: queue)
  236. let expectation = expectation(description: "request should complete")
  237. var response: DataResponse<TestResponse, AFError>?
  238. // When
  239. manager.request(.get).responseDecodable(of: TestResponse.self) { resp in
  240. response = resp
  241. expectation.fulfill()
  242. }
  243. waitForExpectations(timeout: timeout)
  244. // Then
  245. XCTAssertEqual(response?.result.isSuccess, true)
  246. }
  247. @MainActor
  248. func testThatRequestsWorksWithRequestAndSerializationQueues() {
  249. // Given
  250. let requestQueue = DispatchQueue(label: "org.alamofire.testRequestQueue")
  251. let serializationQueue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  252. let manager = Session(requestQueue: requestQueue, serializationQueue: serializationQueue)
  253. let expectation = expectation(description: "request should complete")
  254. var response: DataResponse<TestResponse, AFError>?
  255. // When
  256. manager.request(.get).responseDecodable(of: TestResponse.self) { resp in
  257. response = resp
  258. expectation.fulfill()
  259. }
  260. waitForExpectations(timeout: timeout)
  261. // Then
  262. XCTAssertEqual(response?.result.isSuccess, true)
  263. }
  264. @MainActor
  265. func testThatRequestsWorksWithConcurrentRequestAndSerializationQueues() {
  266. // Given
  267. let requestQueue = DispatchQueue(label: "org.alamofire.testRequestQueue", attributes: .concurrent)
  268. let serializationQueue = DispatchQueue(label: "org.alamofire.testSerializationQueue", attributes: .concurrent)
  269. let session = Session(requestQueue: requestQueue, serializationQueue: serializationQueue)
  270. let count = 10
  271. let expectation = expectation(description: "request should complete")
  272. expectation.expectedFulfillmentCount = count
  273. var responses: [DataResponse<TestResponse, AFError>] = []
  274. // When
  275. DispatchQueue.concurrentPerform(iterations: count) { _ in
  276. session.request(.default).responseDecodable(of: TestResponse.self) { resp in
  277. responses.append(resp)
  278. expectation.fulfill()
  279. }
  280. }
  281. waitForExpectations(timeout: timeout, handler: nil)
  282. // Then
  283. XCTAssertEqual(responses.count, count)
  284. XCTAssertTrue(responses.allSatisfy(\.result.isSuccess))
  285. }
  286. // MARK: Encodable Parameters
  287. @MainActor
  288. func testThatRequestsCanPassEncodableParametersAsJSONBodyData() {
  289. // Given
  290. let parameters = TestParameters(property: "one")
  291. let expect = expectation(description: "request should complete")
  292. var receivedResponse: DataResponse<TestResponse, AFError>?
  293. // When
  294. AF.request(.method(.post), parameters: parameters, encoder: JSONParameterEncoder.default)
  295. .responseDecodable(of: TestResponse.self) { response in
  296. receivedResponse = response
  297. expect.fulfill()
  298. }
  299. waitForExpectations(timeout: timeout)
  300. // Then
  301. XCTAssertEqual(receivedResponse?.result.success?.data, "{\"property\":\"one\"}")
  302. }
  303. @MainActor
  304. func testThatRequestsCanPassEncodableParametersAsAURLQuery() {
  305. // Given
  306. let parameters = TestParameters(property: "one")
  307. let expect = expectation(description: "request should complete")
  308. var receivedResponse: DataResponse<TestResponse, AFError>?
  309. // When
  310. AF.request(.method(.get), parameters: parameters)
  311. .responseDecodable(of: TestResponse.self) { response in
  312. receivedResponse = response
  313. expect.fulfill()
  314. }
  315. waitForExpectations(timeout: timeout)
  316. // Then
  317. XCTAssertEqual(receivedResponse?.result.success?.args, ["property": "one"])
  318. }
  319. @MainActor
  320. func testThatRequestsCanPassEncodableParametersAsURLEncodedBodyData() {
  321. // Given
  322. let parameters = TestParameters(property: "one")
  323. let expect = expectation(description: "request should complete")
  324. var receivedResponse: DataResponse<TestResponse, AFError>?
  325. // When
  326. AF.request(.method(.post), parameters: parameters)
  327. .responseDecodable(of: TestResponse.self) { response in
  328. receivedResponse = response
  329. expect.fulfill()
  330. }
  331. waitForExpectations(timeout: timeout)
  332. // Then
  333. XCTAssertEqual(receivedResponse?.result.success?.form, ["property": "one"])
  334. }
  335. // MARK: Lifetime Events
  336. @MainActor
  337. func testThatAutomaticallyResumedRequestReceivesAppropriateLifetimeEvents() {
  338. // Given
  339. let eventMonitor = ClosureEventMonitor()
  340. let session = Session(eventMonitors: [eventMonitor])
  341. let expect = expectation(description: "request should receive appropriate lifetime events")
  342. expect.expectedFulfillmentCount = 4
  343. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  344. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  345. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  346. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  347. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  348. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  349. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  350. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  351. // When
  352. let request = session.request(.default).response { _ in expect.fulfill() }
  353. waitForExpectations(timeout: timeout)
  354. // Then
  355. XCTAssertEqual(request.state, .finished)
  356. }
  357. @MainActor
  358. func testThatInstanceAutomaticallyResumedRequestReceivesAppropriateLifetimeEvents() {
  359. // Given
  360. let eventMonitor = ClosureEventMonitor()
  361. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  362. let expect = expectation(description: "request should receive appropriate lifetime events")
  363. expect.expectedFulfillmentCount = 4
  364. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  365. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  366. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  367. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  368. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  369. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  370. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  371. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  372. // When
  373. let request = session.request(.default, shouldAutomaticallyResume: true).response { _ in expect.fulfill() }
  374. waitForExpectations(timeout: timeout)
  375. // Then
  376. XCTAssertEqual(request.state, .finished)
  377. }
  378. @MainActor
  379. func testThatAutomaticallyAndManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  380. // Given
  381. let eventMonitor = ClosureEventMonitor()
  382. let session = Session(eventMonitors: [eventMonitor])
  383. let expect = expectation(description: "request should receive appropriate lifetime events")
  384. expect.expectedFulfillmentCount = 4
  385. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  386. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  387. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  388. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  389. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  390. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  391. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  392. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  393. // When
  394. let request = session.request(.default).response { _ in expect.fulfill() }
  395. for _ in 0..<100 {
  396. request.resume()
  397. }
  398. waitForExpectations(timeout: timeout)
  399. // Then
  400. XCTAssertEqual(request.state, .finished)
  401. }
  402. @MainActor
  403. func testThatManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  404. // Given
  405. let eventMonitor = ClosureEventMonitor()
  406. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  407. let expect = expectation(description: "request should receive appropriate lifetime events")
  408. expect.expectedFulfillmentCount = 3
  409. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  410. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  411. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  412. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  413. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  414. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  415. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  416. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  417. // When
  418. let request = session.request(.default)
  419. for _ in 0..<100 {
  420. request.resume()
  421. }
  422. waitForExpectations(timeout: timeout)
  423. // Then
  424. XCTAssertEqual(request.state, .finished)
  425. }
  426. @MainActor
  427. func testThatInstanceManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  428. // Given
  429. let eventMonitor = ClosureEventMonitor()
  430. let session = Session(eventMonitors: [eventMonitor])
  431. let expect = expectation(description: "request should receive appropriate lifetime events")
  432. expect.expectedFulfillmentCount = 3
  433. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  434. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  435. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  436. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  437. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  438. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  439. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  440. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  441. // When
  442. let request = session.request(.default, shouldAutomaticallyResume: false)
  443. for _ in 0..<100 {
  444. request.resume()
  445. }
  446. waitForExpectations(timeout: timeout)
  447. // Then
  448. XCTAssertEqual(request.state, .finished)
  449. }
  450. @MainActor
  451. func testThatRequestManuallyResumedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  452. // Given
  453. let eventMonitor = ClosureEventMonitor()
  454. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  455. let expect = expectation(description: "request should receive appropriate lifetime events")
  456. expect.expectedFulfillmentCount = 4
  457. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  458. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  459. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  460. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  461. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  462. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  463. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  464. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  465. // When
  466. let request = session.request(.default).response { _ in expect.fulfill() }
  467. for _ in 0..<100 {
  468. request.resume()
  469. }
  470. waitForExpectations(timeout: timeout)
  471. // Then
  472. XCTAssertEqual(request.state, .finished)
  473. }
  474. @MainActor
  475. func testThatRequestInstanceManuallyResumedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  476. // Given
  477. let eventMonitor = ClosureEventMonitor()
  478. let session = Session(eventMonitors: [eventMonitor])
  479. let expect = expectation(description: "request should receive appropriate lifetime events")
  480. expect.expectedFulfillmentCount = 4
  481. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  482. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  483. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  484. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  485. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  486. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  487. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  488. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  489. // When
  490. let request = session.request(.default, shouldAutomaticallyResume: false).response { _ in expect.fulfill() }
  491. for _ in 0..<100 {
  492. request.resume()
  493. }
  494. waitForExpectations(timeout: timeout)
  495. // Then
  496. XCTAssertEqual(request.state, .finished)
  497. }
  498. @MainActor
  499. func testThatRequestManuallySuspendedManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  500. // Given
  501. let eventMonitor = ClosureEventMonitor()
  502. let session = Session(startRequestsImmediately: false, requestSetup: .eager, eventMonitors: [eventMonitor])
  503. let expect = expectation(description: "request should receive appropriate lifetime events")
  504. expect.expectedFulfillmentCount = 2
  505. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  506. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  507. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  508. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  509. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  510. // When
  511. let request = session.request(.default)
  512. for _ in 0..<100 {
  513. request.suspend()
  514. }
  515. waitForExpectations(timeout: timeout)
  516. // Then
  517. XCTAssertEqual(request.state, .suspended)
  518. }
  519. @MainActor
  520. func testThatRequestManuallySuspendedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  521. // Given
  522. let eventMonitor = ClosureEventMonitor()
  523. let session = Session(startRequestsImmediately: false, requestSetup: .eager, eventMonitors: [eventMonitor])
  524. let expect = expectation(description: "request should receive appropriate lifetime events")
  525. expect.expectedFulfillmentCount = 2
  526. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  527. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  528. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  529. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  530. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  531. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  532. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  533. // When
  534. let request = session.request(.default)
  535. for _ in 0..<100 {
  536. request.suspend()
  537. }
  538. waitForExpectations(timeout: timeout)
  539. // Then
  540. XCTAssertEqual(request.state, .suspended)
  541. }
  542. @MainActor
  543. func testThatRequestManuallyCancelledManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  544. // Given
  545. let eventMonitor = ClosureEventMonitor()
  546. let session = Session(requestSetup: .eager, eventMonitors: [eventMonitor])
  547. let expect = expectation(description: "request should receive appropriate lifetime events")
  548. expect.expectedFulfillmentCount = 2
  549. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  550. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  551. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  552. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  553. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  554. // When
  555. let request = session.request(.default)
  556. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  557. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  558. for _ in 0..<100 {
  559. request.cancel()
  560. }
  561. }
  562. waitForExpectations(timeout: timeout)
  563. // Then
  564. XCTAssertEqual(request.state, .cancelled)
  565. }
  566. @MainActor
  567. func testThatRequestManuallyCancelledManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  568. // Given
  569. let eventMonitor = ClosureEventMonitor()
  570. let session = Session(startRequestsImmediately: false, requestSetup: .eager, eventMonitors: [eventMonitor])
  571. let expect = expectation(description: "request should receive appropriate lifetime events")
  572. expect.expectedFulfillmentCount = 2
  573. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  574. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  575. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  576. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  577. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  578. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  579. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  580. // When
  581. let request = session.request(.default)
  582. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  583. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  584. for _ in 0..<100 {
  585. request.cancel()
  586. }
  587. }
  588. waitForExpectations(timeout: timeout)
  589. // Then
  590. XCTAssertEqual(request.state, .cancelled)
  591. }
  592. @MainActor
  593. func testThatRequestManuallyCancelledManyTimesOnManyQueuesOnlyReceivesAppropriateLifetimeEvents() {
  594. // Given
  595. let eventMonitor = ClosureEventMonitor()
  596. let session = Session(eventMonitors: [eventMonitor])
  597. let expect = expectation(description: "request should receive appropriate lifetime events")
  598. expect.expectedFulfillmentCount = 6
  599. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  600. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  601. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  602. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  603. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  604. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  605. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  606. // When
  607. let request = session.request(.delay(5)).response { _ in expect.fulfill() }
  608. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  609. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  610. DispatchQueue.concurrentPerform(iterations: 100) { i in
  611. request.cancel()
  612. if i == 99 { expect.fulfill() }
  613. }
  614. }
  615. waitForExpectations(timeout: timeout)
  616. // Then
  617. XCTAssertEqual(request.state, .cancelled)
  618. }
  619. @MainActor
  620. func testThatRequestTriggersAllAppropriateLifetimeEvents() {
  621. // Given
  622. let eventMonitor = ClosureEventMonitor()
  623. let session = Session(eventMonitors: [eventMonitor])
  624. // Disable event test until Firewalk support HTTPS.
  625. // let didReceiveChallenge = expectation(description: "didReceiveChallenge should fire")
  626. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  627. let didReceiveData = expectation(description: "didReceiveData should fire")
  628. let willCacheResponse = expectation(description: "willCacheResponse should fire")
  629. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  630. let didCreateTask = expectation(description: "didCreateTask should fire")
  631. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  632. let didComplete = expectation(description: "didComplete should fire")
  633. let didFinish = expectation(description: "didFinish should fire")
  634. let didResume = expectation(description: "didResume should fire")
  635. let didResumeTask = expectation(description: "didResumeTask should fire")
  636. let didParseResponse = expectation(description: "didParseResponse should fire")
  637. let responseHandler = expectation(description: "responseHandler should fire")
  638. var dataReceived = false
  639. // Disable event test until Firewalk supports HTTPS.
  640. // eventMonitor.taskDidReceiveChallenge = { _, _, _ in didReceiveChallenge.fulfill() }
  641. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  642. eventMonitor.dataTaskDidReceiveData = { _, _, _ in
  643. guard !dataReceived else { return }
  644. // Data may be received many times, fulfill only once.
  645. dataReceived = true
  646. didReceiveData.fulfill()
  647. }
  648. eventMonitor.dataTaskWillCacheResponse = { _, _, _ in willCacheResponse.fulfill() }
  649. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  650. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  651. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  652. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  653. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  654. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  655. eventMonitor.requestDidResumeTask = { _, _ in didResumeTask.fulfill() }
  656. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  657. // When
  658. let request = session.request(.default).response { _ in
  659. responseHandler.fulfill()
  660. }
  661. waitForExpectations(timeout: timeout)
  662. // Then
  663. XCTAssertEqual(request.state, .finished)
  664. }
  665. @MainActor
  666. func testThatCancelledRequestTriggersAllAppropriateLifetimeEvents() {
  667. // Given
  668. let eventMonitor = ClosureEventMonitor()
  669. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  670. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  671. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  672. let didCreateTask = expectation(description: "didCreateTask should fire")
  673. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  674. let didComplete = expectation(description: "didComplete should fire")
  675. let didFinish = expectation(description: "didFinish should fire")
  676. let didResume = expectation(description: "didResume should fire")
  677. let didResumeTask = expectation(description: "didResumeTask should fire")
  678. let didParseResponse = expectation(description: "didParseResponse should fire")
  679. let didCancel = expectation(description: "didCancel should fire")
  680. let didCancelTask = expectation(description: "didCancelTask should fire")
  681. let responseHandler = expectation(description: "responseHandler should fire")
  682. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  683. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  684. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  685. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  686. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  687. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  688. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  689. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  690. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  691. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  692. // When
  693. let request = session.request(.delay(5)).response { _ in
  694. responseHandler.fulfill()
  695. }
  696. eventMonitor.requestDidResumeTask = { [unowned request] _, _ in
  697. request.cancel()
  698. didResumeTask.fulfill()
  699. }
  700. request.resume()
  701. waitForExpectations(timeout: timeout)
  702. // Then
  703. XCTAssertEqual(request.state, .cancelled)
  704. }
  705. @MainActor
  706. func testThatAppendingResponseSerializerToCancelledRequestCallsCompletion() {
  707. // Given
  708. let session = Session()
  709. var response1: DataResponse<TestResponse, AFError>?
  710. var response2: DataResponse<TestResponse, AFError>?
  711. let expect = expectation(description: "both response serializer completions should be called")
  712. expect.expectedFulfillmentCount = 2
  713. // When
  714. let request = session.request(.default)
  715. request.responseDecodable(of: TestResponse.self) { resp in
  716. response1 = resp
  717. expect.fulfill()
  718. request.responseDecodable(of: TestResponse.self) { resp in
  719. response2 = resp
  720. expect.fulfill()
  721. }
  722. }
  723. request.cancel()
  724. waitForExpectations(timeout: timeout)
  725. // Then
  726. XCTAssertEqual(response1?.error?.isExplicitlyCancelledError, true)
  727. XCTAssertEqual(response2?.error?.isExplicitlyCancelledError, true)
  728. }
  729. @MainActor
  730. func testThatAppendingResponseSerializerToCompletedRequestInsideCompletionResumesRequest() {
  731. // Given
  732. let session = Session()
  733. var response1: DataResponse<TestResponse, AFError>?
  734. var response2: DataResponse<TestResponse, AFError>?
  735. var response3: DataResponse<TestResponse, AFError>?
  736. let expect = expectation(description: "all response serializer completions should be called")
  737. expect.expectedFulfillmentCount = 3
  738. // When
  739. let request = session.request(.default)
  740. request.responseDecodable(of: TestResponse.self) { resp in
  741. response1 = resp
  742. expect.fulfill()
  743. request.responseDecodable(of: TestResponse.self) { resp in
  744. response2 = resp
  745. expect.fulfill()
  746. request.responseDecodable(of: TestResponse.self) { resp in
  747. response3 = resp
  748. expect.fulfill()
  749. }
  750. }
  751. }
  752. waitForExpectations(timeout: timeout)
  753. // Then
  754. XCTAssertNotNil(response1?.value)
  755. XCTAssertNotNil(response2?.value)
  756. XCTAssertNotNil(response3?.value)
  757. }
  758. @MainActor
  759. func testThatAppendingResponseSerializerToCompletedRequestOutsideCompletionResumesRequest() {
  760. // Given
  761. let session = Session()
  762. let request = session.request(.default)
  763. var response1: DataResponse<TestResponse, AFError>?
  764. var response2: DataResponse<TestResponse, AFError>?
  765. var response3: DataResponse<TestResponse, AFError>?
  766. // When
  767. let expect1 = expectation(description: "response serializer 1 completion should be called")
  768. request.responseDecodable(of: TestResponse.self) { response1 = $0; expect1.fulfill() }
  769. waitForExpectations(timeout: timeout)
  770. let expect2 = expectation(description: "response serializer 2 completion should be called")
  771. request.responseDecodable(of: TestResponse.self) { response2 = $0; expect2.fulfill() }
  772. waitForExpectations(timeout: timeout)
  773. let expect3 = expectation(description: "response serializer 3 completion should be called")
  774. request.responseDecodable(of: TestResponse.self) { response3 = $0; expect3.fulfill() }
  775. waitForExpectations(timeout: timeout)
  776. // Then
  777. XCTAssertNotNil(response1?.value)
  778. XCTAssertNotNil(response2?.value)
  779. XCTAssertNotNil(response3?.value)
  780. }
  781. }
  782. // MARK: -
  783. final class RequestDescriptionTestCase: BaseTestCase {
  784. @MainActor
  785. func testRequestDescription() {
  786. // Given
  787. let url = Endpoint().url
  788. let manager = Session(startRequestsImmediately: false)
  789. let request = manager.request(url)
  790. let expectation = expectation(description: "Request description should update: \(url)")
  791. var response: HTTPURLResponse?
  792. // When
  793. request.response { resp in
  794. response = resp.response
  795. expectation.fulfill()
  796. }.resume()
  797. waitForExpectations(timeout: timeout)
  798. // Then
  799. XCTAssertEqual(request.description, "GET \(url) (\(response?.statusCode ?? -1))")
  800. }
  801. }
  802. // MARK: -
  803. final class RequestCURLDescriptionTestCase: BaseTestCase {
  804. // MARK: Properties
  805. let session: Session = .init(requestSetup: .eager)
  806. let sessionWithAcceptLanguageHeader: Session = {
  807. var headers = HTTPHeaders.default
  808. headers["Accept-Language"] = "en-US"
  809. let configuration = URLSessionConfiguration.af.default
  810. configuration.headers = headers
  811. let session = Session(configuration: configuration, requestSetup: .eager)
  812. return session
  813. }()
  814. let sessionWithContentTypeHeader: Session = {
  815. var headers = HTTPHeaders.default
  816. headers["Content-Type"] = "application/json"
  817. let configuration = URLSessionConfiguration.af.default
  818. configuration.headers = headers
  819. let session = Session(configuration: configuration, requestSetup: .eager)
  820. return session
  821. }()
  822. func sessionWithCookie(_ cookie: HTTPCookie) -> Session {
  823. let configuration = URLSessionConfiguration.af.default
  824. configuration.httpCookieStorage?.setCookie(cookie)
  825. return Session(configuration: configuration, requestSetup: .eager)
  826. }
  827. let sessionDisallowingCookies: Session = {
  828. let configuration = URLSessionConfiguration.af.default
  829. configuration.httpShouldSetCookies = false
  830. let session = Session(configuration: configuration, requestSetup: .eager)
  831. return session
  832. }()
  833. // MARK: Tests
  834. @MainActor
  835. func testGETRequestCURLDescription() {
  836. // Given
  837. let url = Endpoint().url
  838. let expectation = expectation(description: "request should complete")
  839. var components: [String]?
  840. // When
  841. session.request(url).cURLDescription {
  842. components = self.cURLCommandComponents(from: $0)
  843. expectation.fulfill()
  844. }
  845. // requires eager perform
  846. waitForExpectations(timeout: timeout)
  847. // Then
  848. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  849. XCTAssertTrue(components?.contains("-X") == true)
  850. XCTAssertEqual(components?.last, "\"\(url)\"")
  851. }
  852. @MainActor
  853. func testGETRequestCURLDescriptionOnMainQueue() {
  854. // Given
  855. let url = Endpoint().url
  856. let expectation = expectation(description: "request should complete")
  857. var isMainThread = false
  858. var components: [String]?
  859. // When
  860. session.request(url).cURLDescription(on: .main) {
  861. components = self.cURLCommandComponents(from: $0)
  862. isMainThread = Thread.isMainThread
  863. expectation.fulfill()
  864. }
  865. waitForExpectations(timeout: timeout, handler: nil)
  866. // Then
  867. XCTAssertTrue(isMainThread)
  868. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  869. XCTAssertTrue(components?.contains("-X") == true)
  870. XCTAssertEqual(components?.last, "\"\(url)\"")
  871. }
  872. @MainActor
  873. func testGETRequestCURLDescriptionSynchronous() {
  874. // Given
  875. let url = Endpoint().url
  876. let expectation = expectation(description: "request should complete")
  877. var components: [String]?
  878. var syncComponents: [String]?
  879. // When
  880. let request = session.request(url)
  881. request.cURLDescription {
  882. components = self.cURLCommandComponents(from: $0)
  883. syncComponents = self.cURLCommandComponents(from: request.cURLDescription())
  884. expectation.fulfill()
  885. }
  886. waitForExpectations(timeout: timeout)
  887. // Then
  888. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  889. XCTAssertTrue(components?.contains("-X") == true)
  890. XCTAssertEqual(components?.last, "\"\(url)\"")
  891. XCTAssertEqual(components?.sorted(), syncComponents?.sorted())
  892. }
  893. @MainActor
  894. func testGETRequestCURLDescriptionCanBeRequestedManyTimes() {
  895. // Given
  896. let url = Endpoint().url
  897. let expectation = expectation(description: "request should complete")
  898. var components: [String]?
  899. var secondComponents: [String]?
  900. // When
  901. let request = session.request(url)
  902. request.cURLDescription {
  903. components = self.cURLCommandComponents(from: $0)
  904. request.cURLDescription {
  905. secondComponents = self.cURLCommandComponents(from: $0)
  906. expectation.fulfill()
  907. }
  908. }
  909. waitForExpectations(timeout: timeout)
  910. // Then
  911. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  912. XCTAssertTrue(components?.contains("-X") == true)
  913. XCTAssertEqual(components?.last, "\"\(url)\"")
  914. XCTAssertEqual(components?.sorted(), secondComponents?.sorted())
  915. }
  916. @MainActor
  917. func testGETRequestWithCustomHeaderCURLDescription() {
  918. // Given
  919. let url = Endpoint().url
  920. let expectation = expectation(description: "request should complete")
  921. var cURLDescription: String?
  922. // When
  923. let headers: HTTPHeaders = ["X-Custom-Header": "{\"key\": \"value\"}"]
  924. session.request(url, headers: headers).cURLDescription {
  925. cURLDescription = $0
  926. expectation.fulfill()
  927. }
  928. waitForExpectations(timeout: timeout)
  929. // Then
  930. XCTAssertNotNil(cURLDescription?.range(of: "-H \"X-Custom-Header: {\\\"key\\\": \\\"value\\\"}\""))
  931. }
  932. @MainActor
  933. func testGETRequestWithDuplicateHeadersDebugDescription() {
  934. // Given
  935. let url = Endpoint().url
  936. let expectation = expectation(description: "request should complete")
  937. var cURLDescription: String?
  938. var components: [String]?
  939. // When
  940. let headers: HTTPHeaders = ["Accept-Language": "en-GB"]
  941. sessionWithAcceptLanguageHeader.request(url, headers: headers).cURLDescription {
  942. components = self.cURLCommandComponents(from: $0)
  943. cURLDescription = $0
  944. expectation.fulfill()
  945. }
  946. waitForExpectations(timeout: timeout)
  947. // Then
  948. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  949. XCTAssertTrue(components?.contains("-X") == true)
  950. XCTAssertEqual(components?.last, "\"\(url)\"")
  951. let acceptLanguageCount = components?.count(where: { $0.contains("Accept-Language") })
  952. XCTAssertEqual(acceptLanguageCount, 1, "command should contain a single Accept-Language header")
  953. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Accept-Language: en-GB\""))
  954. }
  955. @MainActor
  956. func testPOSTRequestCURLDescription() {
  957. // Given
  958. let url = Endpoint.method(.post).url
  959. let expectation = expectation(description: "request should complete")
  960. var components: [String]?
  961. // When
  962. session.request(url, method: .post).cURLDescription {
  963. components = self.cURLCommandComponents(from: $0)
  964. expectation.fulfill()
  965. }
  966. waitForExpectations(timeout: timeout)
  967. // Then
  968. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  969. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  970. XCTAssertEqual(components?.last, "\"\(url)\"")
  971. }
  972. @MainActor
  973. func testPOSTRequestWithJSONParametersCURLDescription() {
  974. // Given
  975. let url = Endpoint.method(.post).url
  976. let expectation = expectation(description: "request should complete")
  977. var cURLDescription: String?
  978. var components: [String]?
  979. let parameters = ["foo": "bar",
  980. "fo\"o": "b\"ar",
  981. "f'oo": "ba'r"]
  982. // When
  983. session.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).cURLDescription {
  984. components = self.cURLCommandComponents(from: $0)
  985. cURLDescription = $0
  986. expectation.fulfill()
  987. }
  988. waitForExpectations(timeout: timeout)
  989. // Then
  990. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  991. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  992. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: application/json\""))
  993. XCTAssertNotNil(cURLDescription?.range(of: "-d \"{"))
  994. XCTAssertNotNil(cURLDescription?.range(of: "\\\"f'oo\\\":\\\"ba'r\\\""))
  995. XCTAssertNotNil(cURLDescription?.range(of: "\\\"fo\\\\\\\"o\\\":\\\"b\\\\\\\"ar\\\""))
  996. XCTAssertNotNil(cURLDescription?.range(of: "\\\"foo\\\":\\\"bar\\"))
  997. XCTAssertEqual(components?.last, "\"\(url)\"")
  998. }
  999. @MainActor
  1000. func testPOSTRequestWithCookieCURLDescription() {
  1001. // Given
  1002. let url = Endpoint.method(.post).url
  1003. let cookie = HTTPCookie(properties: [.domain: url.host as Any,
  1004. .path: url.path,
  1005. .name: "foo",
  1006. .value: "bar"])!
  1007. let cookieManager = sessionWithCookie(cookie)
  1008. let expectation = expectation(description: "request should complete")
  1009. var components: [String]?
  1010. // When
  1011. cookieManager.request(url, method: .post).cURLDescription {
  1012. components = self.cURLCommandComponents(from: $0)
  1013. expectation.fulfill()
  1014. }
  1015. waitForExpectations(timeout: timeout)
  1016. // Then
  1017. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  1018. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  1019. XCTAssertEqual(components?.last, "\"\(url)\"")
  1020. XCTAssertEqual(components?[5..<6], ["-b"])
  1021. }
  1022. @MainActor
  1023. func testPOSTRequestWithCookiesDisabledCURLDescriptionHasNoCookies() {
  1024. // Given
  1025. let url = Endpoint.method(.post).url
  1026. let cookie = HTTPCookie(properties: [.domain: url.host as Any,
  1027. .path: url.path,
  1028. .name: "foo",
  1029. .value: "bar"])!
  1030. sessionDisallowingCookies.session.configuration.httpCookieStorage?.setCookie(cookie)
  1031. let expectation = expectation(description: "request should complete")
  1032. var components: [String]?
  1033. // When
  1034. sessionDisallowingCookies.request(url, method: .post).cURLDescription {
  1035. components = self.cURLCommandComponents(from: $0)
  1036. expectation.fulfill()
  1037. }
  1038. waitForExpectations(timeout: timeout)
  1039. // Then
  1040. let cookieComponents = components?.filter { $0 == "-b" }
  1041. XCTAssertTrue(cookieComponents?.isEmpty == true)
  1042. }
  1043. @MainActor
  1044. func testMultipartFormDataRequestWithDuplicateHeadersCURLDescriptionHasOneContentTypeHeader() {
  1045. // Given
  1046. let url = Endpoint.method(.post).url
  1047. let japaneseData = Data("日本語".utf8)
  1048. let expectation = expectation(description: "multipart form data encoding should succeed")
  1049. var cURLDescription: String?
  1050. var components: [String]?
  1051. // When
  1052. sessionWithContentTypeHeader.upload(multipartFormData: { data in
  1053. data.append(japaneseData, withName: "japanese")
  1054. }, to: url).cURLDescription {
  1055. components = self.cURLCommandComponents(from: $0)
  1056. cURLDescription = $0
  1057. expectation.fulfill()
  1058. }
  1059. waitForExpectations(timeout: timeout)
  1060. // Then
  1061. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  1062. XCTAssertTrue(components?.contains("-X") == true)
  1063. XCTAssertEqual(components?.last, "\"\(url)\"")
  1064. let contentTypeCount = components?.count(where: { $0.contains("Content-Type") })
  1065. XCTAssertEqual(contentTypeCount, 1, "command should contain a single Content-Type header")
  1066. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: multipart/form-data;"))
  1067. }
  1068. @MainActor
  1069. func testThatRequestWithInvalidURLDebugDescription() {
  1070. // Given
  1071. let urlString = "invalid_url"
  1072. let expectation = expectation(description: "request should complete")
  1073. var cURLDescription: String?
  1074. // When
  1075. session.request(urlString).cURLDescription {
  1076. cURLDescription = $0
  1077. expectation.fulfill()
  1078. }
  1079. waitForExpectations(timeout: timeout)
  1080. // Then
  1081. XCTAssertNotNil(cURLDescription, "debugDescription should not crash")
  1082. }
  1083. // MARK: Test Helper Methods
  1084. private func cURLCommandComponents(from cURLString: String) -> [String] {
  1085. cURLString.components(separatedBy: .whitespacesAndNewlines)
  1086. .filter { $0 != "" && $0 != "\\" }
  1087. }
  1088. }
  1089. final class RequestLifetimeTests: BaseTestCase {
  1090. @MainActor
  1091. func testThatRequestProvidesURLRequestWhenCreated() {
  1092. // Given
  1093. let didReceiveRequest = expectation(description: "did receive task")
  1094. let didComplete = expectation(description: "request did complete")
  1095. var request: URLRequest?
  1096. // When
  1097. AF.request(.default)
  1098. .onURLRequestCreation { request = $0; didReceiveRequest.fulfill() }
  1099. .responseDecodable(of: TestResponse.self) { _ in didComplete.fulfill() }
  1100. wait(for: [didReceiveRequest, didComplete], timeout: timeout, enforceOrder: true)
  1101. // Then
  1102. XCTAssertNotNil(request)
  1103. }
  1104. @MainActor
  1105. func testThatRequestProvidesTaskWhenCreated() {
  1106. // Given
  1107. let didReceiveTask = expectation(description: "did receive task")
  1108. let didComplete = expectation(description: "request did complete")
  1109. var task: URLSessionTask?
  1110. // When
  1111. AF.request(.default)
  1112. .onURLSessionTaskCreation { task = $0; didReceiveTask.fulfill() }
  1113. .responseDecodable(of: TestResponse.self) { _ in didComplete.fulfill() }
  1114. wait(for: [didReceiveTask, didComplete], timeout: timeout, enforceOrder: true)
  1115. // Then
  1116. XCTAssertNotNil(task)
  1117. }
  1118. }
  1119. // MARK: -
  1120. final class RequestInvalidURLTestCase: BaseTestCase {
  1121. @MainActor
  1122. func testThatDataRequestWithFileURLThrowsError() {
  1123. // Given
  1124. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1125. let expectation = expectation(description: "Request should succeed.")
  1126. var response: DataResponse<Data?, AFError>?
  1127. // When
  1128. AF.request(fileURL)
  1129. .response { resp in
  1130. response = resp
  1131. expectation.fulfill()
  1132. }
  1133. waitForExpectations(timeout: timeout)
  1134. // Then
  1135. XCTAssertEqual(response?.result.isSuccess, true)
  1136. }
  1137. @MainActor
  1138. func testThatDownloadRequestWithFileURLThrowsError() {
  1139. // Given
  1140. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1141. let expectation = expectation(description: "Request should succeed.")
  1142. var response: DownloadResponse<URL?, AFError>?
  1143. // When
  1144. AF.download(fileURL)
  1145. .response { resp in
  1146. response = resp
  1147. expectation.fulfill()
  1148. }
  1149. waitForExpectations(timeout: timeout)
  1150. // Then
  1151. XCTAssertEqual(response?.result.isSuccess, true)
  1152. }
  1153. @MainActor
  1154. func testThatDataStreamRequestWithFileURLThrowsError() {
  1155. // Given
  1156. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1157. let expectation = expectation(description: "Request should succeed.")
  1158. var response: DataStreamRequest.Completion?
  1159. // When
  1160. AF.streamRequest(fileURL)
  1161. .responseStream { stream in
  1162. guard case let .complete(completion) = stream.event else { return }
  1163. response = completion
  1164. expectation.fulfill()
  1165. }
  1166. waitForExpectations(timeout: timeout)
  1167. // Then
  1168. XCTAssertNil(response?.response)
  1169. }
  1170. }
  1171. @Suite
  1172. struct RequestInstanceInterceptorTests {
  1173. @Test
  1174. func instanceAdapterIsCalled() async throws {
  1175. // Given
  1176. let session = Session()
  1177. let adapter = InspectorInterceptor(.adapter { @Sendable request, _, completion in completion(.success(request)) })
  1178. // When
  1179. let response = await session
  1180. .request(.get)
  1181. .adapt(using: adapter)
  1182. .serializingDecodable(TestResponse.self).response
  1183. #expect(response.result.isSuccess)
  1184. #expect(adapter.adaptations.count == 1)
  1185. }
  1186. @Test
  1187. func instanceAdaptersAreCalledInAddedOrder() async throws {
  1188. // Given
  1189. let session = Session()
  1190. let firstAdapter = InspectorInterceptor(.adapter { @Sendable request, _, completion in completion(.success(request)) })
  1191. let secondAdapter = InspectorInterceptor(.adapter { @Sendable request, _, completion in completion(.success(request)) })
  1192. // When
  1193. let response = await session
  1194. .request(.get)
  1195. .adapt(using: firstAdapter)
  1196. .adapt(using: secondAdapter)
  1197. .serializingDecodable(TestResponse.self).response
  1198. #expect(response.result.isSuccess)
  1199. #expect(firstAdapter.adaptations.count == 1)
  1200. #expect(secondAdapter.adaptations.count == 1)
  1201. #expect(firstAdapter.adaptations[0].date < secondAdapter.adaptations[0].date)
  1202. }
  1203. @Test
  1204. func sessionAdapterIsCalledBeforeInstanceAdapter() async throws {
  1205. // Given
  1206. let sessionInterceptor = InspectorInterceptor(.adapter { @Sendable request, _, completion in
  1207. var request = request
  1208. request.headers["session"] = "\(Date.now.timeIntervalSince1970)"
  1209. completion(.success(request))
  1210. })
  1211. let session = Session(interceptor: sessionInterceptor)
  1212. let instanceInterceptor = InspectorInterceptor(.adapter { @Sendable request, _, completion in
  1213. var request = request
  1214. request.headers["instance"] = "\(Date.now.timeIntervalSince1970)"
  1215. completion(.success(request))
  1216. })
  1217. // When
  1218. let response = await session
  1219. .request(.get)
  1220. .adapt(using: instanceInterceptor)
  1221. .serializingDecodable(TestResponse.self).response
  1222. #expect(response.result.isSuccess)
  1223. if let sessionTime = response.request?.headers["session"].flatMap(Double.init),
  1224. let instanceTime = response.request?.headers["instance"].flatMap(Double.init) {
  1225. #expect(sessionTime < instanceTime)
  1226. }
  1227. #expect(sessionInterceptor.adaptations.count == 1)
  1228. #expect(instanceInterceptor.adaptations.count == 1)
  1229. #expect(sessionInterceptor.adaptations[0].date < instanceInterceptor.adaptations[0].date)
  1230. }
  1231. @Test
  1232. func instanceInterceptorIsCalled() async throws {
  1233. // Given
  1234. let session = Session()
  1235. let interceptor = InspectorInterceptor(
  1236. .interceptor { @Sendable request, _, completion in
  1237. completion(.success(request))
  1238. } retrier: { @Sendable _, _, _, completion in
  1239. completion(.retry)
  1240. }
  1241. )
  1242. // When
  1243. let response = await session
  1244. .request(.endpoints(.delay(1).modifying(\.timeout, to: 0.0001), .get))
  1245. .interceptor(interceptor)
  1246. .serializingDecodable(TestResponse.self).response
  1247. #expect(response.result.isSuccess)
  1248. #expect(interceptor.adaptations.count == 2)
  1249. #expect(interceptor.retries.count == 1)
  1250. }
  1251. @Test
  1252. func multipleInstanceInterceptorsAreCalledInAddedOrder() async throws {
  1253. // Given
  1254. let session = Session()
  1255. let firstInterceptor = InspectorInterceptor(
  1256. .interceptor { @Sendable request, _, completion in
  1257. completion(.success(request))
  1258. } retrier: { @Sendable _, _, _, completion in
  1259. completion(.doNotRetry)
  1260. }
  1261. )
  1262. let secondInterceptor = InspectorInterceptor(
  1263. .interceptor { @Sendable request, _, completion in
  1264. completion(.success(request))
  1265. } retrier: { @Sendable _, _, _, completion in
  1266. completion(.retry)
  1267. }
  1268. )
  1269. // When
  1270. let response = await session
  1271. .request(.endpoints(.delay(1).modifying(\.timeout, to: 0.0001), .get))
  1272. .interceptor(firstInterceptor)
  1273. .interceptor(secondInterceptor)
  1274. .serializingDecodable(TestResponse.self).response
  1275. #expect(response.result.isSuccess)
  1276. #expect(firstInterceptor.adaptations.count == 2)
  1277. #expect(firstInterceptor.retries.count == 1)
  1278. #expect(secondInterceptor.adaptations.count == 2)
  1279. #expect(secondInterceptor.retries.count == 1)
  1280. #expect(firstInterceptor.adaptations[0].date < secondInterceptor.adaptations[0].date)
  1281. #expect(firstInterceptor.adaptations[1].date < secondInterceptor.adaptations[1].date)
  1282. #expect(firstInterceptor.retries[0].date < secondInterceptor.retries[0].date)
  1283. }
  1284. @Test
  1285. func instanceRetrierIsCalled() async throws {
  1286. // Given
  1287. let session = Session()
  1288. let interceptor = InspectorInterceptor(.retrier { @Sendable _, _, _, completion in completion(.retry) })
  1289. // When
  1290. let response = await session
  1291. .request(.endpoints(.delay(1).modifying(\.timeout, to: 0.0001), .get))
  1292. .retry(using: interceptor)
  1293. .serializingDecodable(TestResponse.self).response
  1294. #expect(response.result.isSuccess)
  1295. #expect(interceptor.retries.count == 1)
  1296. }
  1297. @Test
  1298. func multipleInstanceRetriersAreCalledInAddedOrder() async throws {
  1299. // Given
  1300. let session = Session()
  1301. let firstRetrier = InspectorInterceptor(.retrier { @Sendable _, _, _, completion in completion(.doNotRetry) })
  1302. let secondRetrier = InspectorInterceptor(.retrier { @Sendable _, _, _, completion in completion(.retry) })
  1303. // When
  1304. let response = await session
  1305. .request(.endpoints(.delay(1).modifying(\.timeout, to: 0.0001), .get))
  1306. .retry(using: firstRetrier)
  1307. .retry(using: secondRetrier)
  1308. .serializingDecodable(TestResponse.self).response
  1309. #expect(response.result.isSuccess)
  1310. #expect(firstRetrier.retries.count == 1)
  1311. #expect(secondRetrier.retries.count == 1)
  1312. #expect(firstRetrier.retries[0].date < secondRetrier.retries[0].date)
  1313. }
  1314. @Test
  1315. func sessionRetrierIsCalledBeforeInstanceRetrier() async throws {
  1316. // Given
  1317. let sessionRetrier = InspectorInterceptor(.retrier { @Sendable _, _, _, completion in completion(.doNotRetry) })
  1318. let session = Session(interceptor: sessionRetrier)
  1319. let instanceRetrier = InspectorInterceptor(.retrier { @Sendable _, _, _, completion in completion(.retry) })
  1320. // When
  1321. let response = await session
  1322. .request(.endpoints(.delay(1).modifying(\.timeout, to: 0.0001), .get))
  1323. .retry(using: instanceRetrier)
  1324. .serializingDecodable(TestResponse.self).response
  1325. #expect(response.result.isSuccess)
  1326. #expect(instanceRetrier.retries.count == 1)
  1327. #expect(sessionRetrier.retries.count == 1)
  1328. #expect(sessionRetrier.retries[0].date < instanceRetrier.retries[0].date)
  1329. }
  1330. @Test
  1331. func instanceEventMonitorIsCalled() async throws {
  1332. // Given
  1333. let queue = DispatchQueue(label: "org.alamofire.\(#function)")
  1334. let monitor = InspectorEventMonitor(queue: queue)
  1335. let session = Session(rootQueue: queue, eventMonitors: [])
  1336. // When
  1337. let response = await session
  1338. .request(.get)
  1339. .eventMonitor(monitor)
  1340. .serializingDecodable(TestResponse.self)
  1341. .response
  1342. await monitor.pendingEvents()
  1343. // Then
  1344. #expect(response.result.isSuccess)
  1345. let expected = ["requestDidResume(_:)",
  1346. "request(_:didCreateInitialURLRequest:)",
  1347. "request(_:didCreateURLRequest:)",
  1348. "request(_:didCreateTask:)",
  1349. "request(_:didResumeTask:)",
  1350. "request(_:didGatherMetrics:)",
  1351. "requestDidFinish(_:)",
  1352. "request(_:didParseResponse:)"]
  1353. #expect(monitor.events == expected, "Events didn't match, actual events: \(monitor.events)")
  1354. }
  1355. @Test
  1356. func multipleInstanceEventMonitorsAreCalledInAddedOrder() async throws {
  1357. // Given
  1358. let queue = DispatchQueue(label: "org.alamofire.\(#function)")
  1359. let firstMonitor = InspectorEventMonitor(queue: queue)
  1360. let secondMonitor = InspectorEventMonitor(queue: queue)
  1361. let session = Session(rootQueue: queue, eventMonitors: [])
  1362. // When
  1363. let response = await session
  1364. .request(.get)
  1365. .eventMonitor(firstMonitor)
  1366. .eventMonitor(secondMonitor)
  1367. .serializingDecodable(TestResponse.self)
  1368. .response
  1369. await firstMonitor.pendingEvents()
  1370. // Then
  1371. #expect(response.result.isSuccess)
  1372. let expected = ["requestDidResume(_:)",
  1373. "request(_:didCreateInitialURLRequest:)",
  1374. "request(_:didCreateURLRequest:)",
  1375. "request(_:didCreateTask:)",
  1376. "request(_:didResumeTask:)",
  1377. "request(_:didGatherMetrics:)",
  1378. "requestDidFinish(_:)",
  1379. "request(_:didParseResponse:)"]
  1380. #expect(firstMonitor.events == expected, "firstMonitor events didn't match, actual events: \(firstMonitor.events)")
  1381. #expect(secondMonitor.events == expected, "secondMonitor events didn't match, actual events: \(firstMonitor.events)")
  1382. for timelines in zip(firstMonitor.timeline, secondMonitor.timeline) {
  1383. #expect(timelines.0.date <= timelines.1.date)
  1384. }
  1385. }
  1386. @Test
  1387. func instanceAndSessionEventMonitorsAreCalledInCorrectOrder() async throws {
  1388. // Given
  1389. let queue = DispatchQueue(label: "org.alamofire.\(#function)")
  1390. let sessionMonitor = InspectorEventMonitor(label: "session", queue: queue)
  1391. let instanceMonitor = InspectorEventMonitor(label: "instance", queue: queue)
  1392. let session = Session(rootQueue: queue, eventMonitors: [sessionMonitor])
  1393. // When
  1394. let response = await session
  1395. .request(.get)
  1396. .eventMonitor(instanceMonitor)
  1397. .serializingDecodable(TestResponse.self)
  1398. .response
  1399. await sessionMonitor.pendingEvents()
  1400. await instanceMonitor.pendingEvents()
  1401. // Then
  1402. #expect(response.result.isSuccess)
  1403. let expectedInstanceEvents = ["requestDidResume(_:)",
  1404. "request(_:didCreateInitialURLRequest:)",
  1405. "request(_:didCreateURLRequest:)",
  1406. "request(_:didCreateTask:)",
  1407. "request(_:didResumeTask:)",
  1408. "request(_:didGatherMetrics:)",
  1409. "requestDidFinish(_:)",
  1410. "request(_:didParseResponse:)"]
  1411. let expectedSessionEvents = ["requestDidResume(_:)",
  1412. "request(_:didCreateInitialURLRequest:)",
  1413. "request(_:didCreateURLRequest:)",
  1414. "request(_:didCreateTask:)",
  1415. "request(_:didResumeTask:)",
  1416. "urlSession(_:dataTask:didReceive:)",
  1417. "urlSession(_:dataTask:willCacheResponse:)",
  1418. "urlSession(_:task:didFinishCollecting:)",
  1419. "request(_:didGatherMetrics:)",
  1420. "urlSession(_:task:didCompleteWithError:)",
  1421. "requestDidFinish(_:)",
  1422. "request(_:didParseResponse:)"]
  1423. #expect(sessionMonitor.events == expectedSessionEvents, "Session events didn't match, actual events: \(sessionMonitor.events)")
  1424. #expect(instanceMonitor.events == expectedInstanceEvents, "Instance events didn't match, actual events: \(instanceMonitor.events)")
  1425. let instanceEvents = instanceMonitor.timeline
  1426. var sessionEvents = sessionMonitor.timeline
  1427. sessionEvents = sessionEvents.filter { session in instanceEvents.contains { $0.event == session.event } }
  1428. #expect(instanceEvents.count == sessionEvents.count)
  1429. for combinedEvent in zip(sessionEvents, instanceEvents) {
  1430. #expect(combinedEvent.0.event == combinedEvent.1.event)
  1431. #expect(combinedEvent.0.date <= combinedEvent.1.date, "session event wasn't before instance event")
  1432. }
  1433. }
  1434. }
  1435. #if canImport(zlib) && !os(Android) // Same condition as `DeflateRequestCompressor`.
  1436. @Suite
  1437. struct RequestCompressionTests {
  1438. @Test
  1439. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1440. func thatRequestsCanBeCompressed() async {
  1441. // Given
  1442. let url = Endpoint.method(.post).url
  1443. let parameters = TestParameters(property: "compressed")
  1444. // When
  1445. let result = await AF.request(url,
  1446. method: .post,
  1447. parameters: parameters,
  1448. encoder: .json,
  1449. interceptor: .deflateCompressor)
  1450. .serializingDecodable(TestResponse.self)
  1451. .result
  1452. // Then
  1453. #expect(result.isSuccess)
  1454. }
  1455. @Test
  1456. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1457. func thatDeflateCompressorThrowsErrorByDefaultWhenRequestAlreadyHasHeader() async {
  1458. // Given
  1459. let url = Endpoint.method(.post).url
  1460. let parameters = TestParameters(property: "compressed")
  1461. // When
  1462. let result = await AF.request(url,
  1463. method: .post,
  1464. parameters: parameters,
  1465. encoder: .json,
  1466. headers: [.contentEncoding("value")],
  1467. interceptor: .deflateCompressor)
  1468. .serializingDecodable(TestResponse.self)
  1469. .result
  1470. // Then
  1471. #expect(result.isFailure)
  1472. #expect(result.failure?.underlyingError as? DeflateRequestCompressor.DuplicateHeaderError != nil)
  1473. }
  1474. @Test
  1475. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1476. func thatDeflateCompressorThrowsErrorWhenConfigured() async {
  1477. // Given
  1478. let url = Endpoint.method(.post).url
  1479. let parameters = TestParameters(property: "compressed")
  1480. // When
  1481. let result = await AF.request(url,
  1482. method: .post,
  1483. parameters: parameters,
  1484. encoder: .json,
  1485. headers: [.contentEncoding("value")],
  1486. interceptor: .deflateCompressor(duplicateHeaderBehavior: .error))
  1487. .serializingDecodable(TestResponse.self)
  1488. .result
  1489. // Then
  1490. #expect(result.isFailure)
  1491. #expect(result.failure?.underlyingError as? DeflateRequestCompressor.DuplicateHeaderError != nil)
  1492. }
  1493. @Test
  1494. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1495. func thatDeflateCompressorReplacesHeaderWhenConfigured() async {
  1496. // Given
  1497. let url = Endpoint.method(.post).url
  1498. let parameters = TestParameters(property: "compressed")
  1499. // When
  1500. let result = await AF.request(url,
  1501. method: .post,
  1502. parameters: parameters,
  1503. encoder: .json,
  1504. headers: [.contentEncoding("value")],
  1505. interceptor: .deflateCompressor(duplicateHeaderBehavior: .replace))
  1506. .serializingDecodable(TestResponse.self)
  1507. .result
  1508. // Then
  1509. #expect(result.isSuccess)
  1510. }
  1511. @Test
  1512. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1513. func thatDeflateCompressorSkipsCompressionWhenConfigured() async {
  1514. // Given
  1515. let url = Endpoint.method(.post).url
  1516. let parameters = TestParameters(property: "compressed")
  1517. // When
  1518. let result = await AF.request(url,
  1519. method: .post,
  1520. parameters: parameters,
  1521. encoder: .json,
  1522. headers: [.contentEncoding("gzip")],
  1523. interceptor: .deflateCompressor(duplicateHeaderBehavior: .skip))
  1524. .serializingDecodable(TestResponse.self)
  1525. .result
  1526. // Then
  1527. // Request fails as the server expects gzip compression.
  1528. #expect(result.isFailure)
  1529. }
  1530. @Test
  1531. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1532. func thatDeflateCompressorDoesNotCompressDataWhenClosureReturnsFalse() async {
  1533. // Given
  1534. let url = Endpoint.method(.post).url
  1535. let parameters = TestParameters(property: "compressed")
  1536. // When
  1537. let result = await AF.request(url,
  1538. method: .post,
  1539. parameters: parameters,
  1540. encoder: .json,
  1541. interceptor: .deflateCompressor { _ in false })
  1542. .serializingDecodable(TestResponse.self)
  1543. .result
  1544. // Then
  1545. #expect(result.isSuccess)
  1546. // With no compression, request headers reflected from server should have no Content-Encoding.
  1547. #expect(result.success?.headers["Content-Encoding"] == nil)
  1548. }
  1549. }
  1550. #endif