RequestTests.swift 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496
  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 XCTest
  27. final class RequestResponseTestCase: BaseTestCase {
  28. @MainActor
  29. func testRequestResponse() {
  30. // Given
  31. let url = Endpoint.get.url
  32. let expectation = expectation(description: "GET request should succeed: \(url)")
  33. var response: DataResponse<Data?, AFError>?
  34. // When
  35. AF.request(url, parameters: ["foo": "bar"])
  36. .response { resp in
  37. response = resp
  38. expectation.fulfill()
  39. }
  40. waitForExpectations(timeout: timeout)
  41. // Then
  42. XCTAssertNotNil(response?.request)
  43. XCTAssertNotNil(response?.response)
  44. XCTAssertNotNil(response?.data)
  45. XCTAssertNil(response?.error)
  46. }
  47. @MainActor
  48. func testThatDataRequestReceivesInitialResponse() {
  49. // Given
  50. let url = Endpoint.get.url
  51. var initialResponse: HTTPURLResponse?
  52. let didReceiveResponse = expectation(description: "didReceiveResponse")
  53. let didComplete = expectation(description: "GET request should succeed: \(url)")
  54. var response: DataResponse<Data?, AFError>?
  55. // When
  56. AF.request(url, parameters: ["foo": "bar"])
  57. .onHTTPResponse { response in
  58. initialResponse = response
  59. didReceiveResponse.fulfill()
  60. }
  61. .response { resp in
  62. response = resp
  63. didComplete.fulfill()
  64. }
  65. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  66. // Then
  67. XCTAssertEqual(initialResponse, response?.response)
  68. XCTAssertNotNil(response?.request)
  69. XCTAssertNotNil(response?.response)
  70. XCTAssertNotNil(response?.data)
  71. XCTAssertNil(response?.error)
  72. }
  73. @MainActor
  74. func testThatDataRequestOnHTTPResponseCanAllow() {
  75. // Given
  76. let url = Endpoint.get.url
  77. var initialResponse: HTTPURLResponse?
  78. let didReceiveResponse = expectation(description: "didReceiveResponse")
  79. let didComplete = expectation(description: "GET request should succeed: \(url)")
  80. var response: DataResponse<Data?, AFError>?
  81. // When
  82. AF.request(url, parameters: ["foo": "bar"])
  83. .onHTTPResponse { response, completionHandler in
  84. initialResponse = response
  85. didReceiveResponse.fulfill()
  86. completionHandler(.allow)
  87. }
  88. .response { resp in
  89. response = resp
  90. didComplete.fulfill()
  91. }
  92. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  93. // Then
  94. XCTAssertEqual(initialResponse, response?.response)
  95. XCTAssertNotNil(response?.request)
  96. XCTAssertNotNil(response?.response)
  97. XCTAssertNotNil(response?.data)
  98. XCTAssertNil(response?.error)
  99. }
  100. @MainActor
  101. func testThatDataRequestOnHTTPResponseCanCancel() {
  102. // Given
  103. let url = Endpoint.get.url
  104. var initialResponse: HTTPURLResponse?
  105. let didReceiveResponse = expectation(description: "didReceiveResponse")
  106. let didComplete = expectation(description: "GET request should succeed: \(url)")
  107. var response: DataResponse<Data?, AFError>?
  108. // When
  109. let request = AF.request(url, parameters: ["foo": "bar"])
  110. .onHTTPResponse { response, completionHandler in
  111. initialResponse = response
  112. didReceiveResponse.fulfill()
  113. completionHandler(.cancel)
  114. }
  115. .response { resp in
  116. response = resp
  117. didComplete.fulfill()
  118. }
  119. wait(for: [didReceiveResponse, didComplete], timeout: timeout, enforceOrder: true)
  120. // Then
  121. XCTAssertEqual(initialResponse, response?.response)
  122. XCTAssertNotNil(response?.request)
  123. XCTAssertNotNil(response?.response)
  124. XCTAssertNil(response?.data)
  125. XCTAssertTrue(request.isCancelled, "onHTTPResponse cancelled request should have isCancelled == true")
  126. XCTAssertTrue(response?.error?.isExplicitlyCancelledError == true, "onHTTPResponse cancelled request should be explicitly cancelled")
  127. }
  128. @MainActor
  129. func testRequestResponseWithProgress() {
  130. // Given
  131. let byteCount = 512
  132. let url = Endpoint.bytes(byteCount).url
  133. let expectation = expectation(description: "Bytes download progress should be reported: \(url)")
  134. var progressValues: [Double] = []
  135. var response: DataResponse<Data?, AFError>?
  136. // When
  137. AF.request(url)
  138. .downloadProgress { progress in
  139. progressValues.append(progress.fractionCompleted)
  140. }
  141. .response { resp in
  142. response = resp
  143. expectation.fulfill()
  144. }
  145. waitForExpectations(timeout: timeout)
  146. // Then
  147. XCTAssertNotNil(response?.request)
  148. XCTAssertNotNil(response?.response)
  149. XCTAssertNotNil(response?.data)
  150. XCTAssertNil(response?.error)
  151. var previousProgress: Double = progressValues.first ?? 0.0
  152. for progress in progressValues {
  153. XCTAssertGreaterThanOrEqual(progress, previousProgress)
  154. previousProgress = progress
  155. }
  156. if let lastProgressValue = progressValues.last {
  157. XCTAssertEqual(lastProgressValue, 1.0)
  158. } else {
  159. XCTFail("last item in progressValues should not be nil")
  160. }
  161. }
  162. @MainActor
  163. func testPOSTRequestWithUnicodeParameters() {
  164. // Given
  165. let parameters = ["french": "français",
  166. "japanese": "日本語",
  167. "arabic": "العربية",
  168. "emoji": "😃"]
  169. let expectation = expectation(description: "request should succeed")
  170. var response: DataResponse<TestResponse, AFError>?
  171. // When
  172. AF.request(.method(.post), parameters: parameters)
  173. .responseDecodable(of: TestResponse.self) { closureResponse in
  174. response = closureResponse
  175. expectation.fulfill()
  176. }
  177. waitForExpectations(timeout: timeout)
  178. // Then
  179. XCTAssertNotNil(response?.request)
  180. XCTAssertNotNil(response?.response)
  181. XCTAssertNotNil(response?.data)
  182. if let form = response?.result.success?.form {
  183. XCTAssertEqual(form["french"], parameters["french"])
  184. XCTAssertEqual(form["japanese"], parameters["japanese"])
  185. XCTAssertEqual(form["arabic"], parameters["arabic"])
  186. XCTAssertEqual(form["emoji"], parameters["emoji"])
  187. } else {
  188. XCTFail("form parameter in JSON should not be nil")
  189. }
  190. }
  191. @MainActor
  192. func testPOSTRequestWithBase64EncodedImages() {
  193. // Given
  194. let pngBase64EncodedString: String = {
  195. let fileURL = url(forResource: "unicorn", withExtension: "png")
  196. let data = try! Data(contentsOf: fileURL)
  197. return data.base64EncodedString(options: .lineLength64Characters)
  198. }()
  199. let jpegBase64EncodedString: String = {
  200. let fileURL = url(forResource: "rainbow", withExtension: "jpg")
  201. let data = try! Data(contentsOf: fileURL)
  202. return data.base64EncodedString(options: .lineLength64Characters)
  203. }()
  204. let parameters = ["email": "user@alamofire.org",
  205. "png_image": pngBase64EncodedString,
  206. "jpeg_image": jpegBase64EncodedString]
  207. let expectation = expectation(description: "request should succeed")
  208. var response: DataResponse<TestResponse, AFError>?
  209. // When
  210. AF.request(Endpoint.method(.post), method: .post, parameters: parameters)
  211. .responseDecodable(of: TestResponse.self) { closureResponse in
  212. response = closureResponse
  213. expectation.fulfill()
  214. }
  215. waitForExpectations(timeout: timeout)
  216. // Then
  217. XCTAssertNotNil(response?.request)
  218. XCTAssertNotNil(response?.response)
  219. XCTAssertNotNil(response?.data)
  220. XCTAssertEqual(response?.result.isSuccess, true)
  221. if let form = response?.result.success?.form {
  222. XCTAssertEqual(form["email"], parameters["email"])
  223. XCTAssertEqual(form["png_image"], parameters["png_image"])
  224. XCTAssertEqual(form["jpeg_image"], parameters["jpeg_image"])
  225. } else {
  226. XCTFail("form parameter in JSON should not be nil")
  227. }
  228. }
  229. // MARK: Queues
  230. @MainActor
  231. func testThatResponseSerializationWorksWithSerializationQueue() {
  232. // Given
  233. let queue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  234. let manager = Session(serializationQueue: queue)
  235. let expectation = expectation(description: "request should complete")
  236. var response: DataResponse<TestResponse, AFError>?
  237. // When
  238. manager.request(.get).responseDecodable(of: TestResponse.self) { resp in
  239. response = resp
  240. expectation.fulfill()
  241. }
  242. waitForExpectations(timeout: timeout)
  243. // Then
  244. XCTAssertEqual(response?.result.isSuccess, true)
  245. }
  246. @MainActor
  247. func testThatRequestsWorksWithRequestAndSerializationQueues() {
  248. // Given
  249. let requestQueue = DispatchQueue(label: "org.alamofire.testRequestQueue")
  250. let serializationQueue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  251. let manager = Session(requestQueue: requestQueue, serializationQueue: serializationQueue)
  252. let expectation = expectation(description: "request should complete")
  253. var response: DataResponse<TestResponse, AFError>?
  254. // When
  255. manager.request(.get).responseDecodable(of: TestResponse.self) { resp in
  256. response = resp
  257. expectation.fulfill()
  258. }
  259. waitForExpectations(timeout: timeout)
  260. // Then
  261. XCTAssertEqual(response?.result.isSuccess, true)
  262. }
  263. @MainActor
  264. func testThatRequestsWorksWithConcurrentRequestAndSerializationQueues() {
  265. // Given
  266. let requestQueue = DispatchQueue(label: "org.alamofire.testRequestQueue", attributes: .concurrent)
  267. let serializationQueue = DispatchQueue(label: "org.alamofire.testSerializationQueue", attributes: .concurrent)
  268. let session = Session(requestQueue: requestQueue, serializationQueue: serializationQueue)
  269. let count = 10
  270. let expectation = expectation(description: "request should complete")
  271. expectation.expectedFulfillmentCount = count
  272. var responses: [DataResponse<TestResponse, AFError>] = []
  273. // When
  274. DispatchQueue.concurrentPerform(iterations: count) { _ in
  275. session.request(.default).responseDecodable(of: TestResponse.self) { resp in
  276. responses.append(resp)
  277. expectation.fulfill()
  278. }
  279. }
  280. waitForExpectations(timeout: timeout, handler: nil)
  281. // Then
  282. XCTAssertEqual(responses.count, count)
  283. XCTAssertTrue(responses.allSatisfy(\.result.isSuccess))
  284. }
  285. // MARK: Encodable Parameters
  286. @MainActor
  287. func testThatRequestsCanPassEncodableParametersAsJSONBodyData() {
  288. // Given
  289. let parameters = TestParameters(property: "one")
  290. let expect = expectation(description: "request should complete")
  291. var receivedResponse: DataResponse<TestResponse, AFError>?
  292. // When
  293. AF.request(.method(.post), parameters: parameters, encoder: JSONParameterEncoder.default)
  294. .responseDecodable(of: TestResponse.self) { response in
  295. receivedResponse = response
  296. expect.fulfill()
  297. }
  298. waitForExpectations(timeout: timeout)
  299. // Then
  300. XCTAssertEqual(receivedResponse?.result.success?.data, "{\"property\":\"one\"}")
  301. }
  302. @MainActor
  303. func testThatRequestsCanPassEncodableParametersAsAURLQuery() {
  304. // Given
  305. let parameters = TestParameters(property: "one")
  306. let expect = expectation(description: "request should complete")
  307. var receivedResponse: DataResponse<TestResponse, AFError>?
  308. // When
  309. AF.request(.method(.get), parameters: parameters)
  310. .responseDecodable(of: TestResponse.self) { response in
  311. receivedResponse = response
  312. expect.fulfill()
  313. }
  314. waitForExpectations(timeout: timeout)
  315. // Then
  316. XCTAssertEqual(receivedResponse?.result.success?.args, ["property": "one"])
  317. }
  318. @MainActor
  319. func testThatRequestsCanPassEncodableParametersAsURLEncodedBodyData() {
  320. // Given
  321. let parameters = TestParameters(property: "one")
  322. let expect = expectation(description: "request should complete")
  323. var receivedResponse: DataResponse<TestResponse, AFError>?
  324. // When
  325. AF.request(.method(.post), parameters: parameters)
  326. .responseDecodable(of: TestResponse.self) { response in
  327. receivedResponse = response
  328. expect.fulfill()
  329. }
  330. waitForExpectations(timeout: timeout)
  331. // Then
  332. XCTAssertEqual(receivedResponse?.result.success?.form, ["property": "one"])
  333. }
  334. // MARK: Lifetime Events
  335. @MainActor
  336. func testThatAutomaticallyResumedRequestReceivesAppropriateLifetimeEvents() {
  337. // Given
  338. let eventMonitor = ClosureEventMonitor()
  339. let session = Session(eventMonitors: [eventMonitor])
  340. let expect = expectation(description: "request should receive appropriate lifetime events")
  341. expect.expectedFulfillmentCount = 4
  342. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  343. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  344. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  345. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  346. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  347. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  348. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  349. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  350. // When
  351. let request = session.request(.default).response { _ in expect.fulfill() }
  352. waitForExpectations(timeout: timeout)
  353. // Then
  354. XCTAssertEqual(request.state, .finished)
  355. }
  356. @MainActor
  357. func testThatAutomaticallyAndManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  358. // Given
  359. let eventMonitor = ClosureEventMonitor()
  360. let session = Session(eventMonitors: [eventMonitor])
  361. let expect = expectation(description: "request should receive appropriate lifetime events")
  362. expect.expectedFulfillmentCount = 4
  363. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  364. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  365. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  366. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  367. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  368. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  369. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  370. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  371. // When
  372. let request = session.request(.default).response { _ in expect.fulfill() }
  373. for _ in 0..<100 {
  374. request.resume()
  375. }
  376. waitForExpectations(timeout: timeout)
  377. // Then
  378. XCTAssertEqual(request.state, .finished)
  379. }
  380. @MainActor
  381. func testThatManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  382. // Given
  383. let eventMonitor = ClosureEventMonitor()
  384. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  385. let expect = expectation(description: "request should receive appropriate lifetime events")
  386. expect.expectedFulfillmentCount = 3
  387. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  388. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  389. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  390. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  391. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  392. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  393. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  394. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  395. // When
  396. let request = session.request(.default)
  397. for _ in 0..<100 {
  398. request.resume()
  399. }
  400. waitForExpectations(timeout: timeout)
  401. // Then
  402. XCTAssertEqual(request.state, .finished)
  403. }
  404. @MainActor
  405. func testThatRequestManuallyResumedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  406. // Given
  407. let eventMonitor = ClosureEventMonitor()
  408. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  409. let expect = expectation(description: "request should receive appropriate lifetime events")
  410. expect.expectedFulfillmentCount = 4
  411. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  412. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  413. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  414. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  415. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  416. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  417. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  418. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  419. // When
  420. let request = session.request(.default).response { _ in expect.fulfill() }
  421. for _ in 0..<100 {
  422. request.resume()
  423. }
  424. waitForExpectations(timeout: timeout)
  425. // Then
  426. XCTAssertEqual(request.state, .finished)
  427. }
  428. @MainActor
  429. func testThatRequestManuallySuspendedManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  430. // Given
  431. let eventMonitor = ClosureEventMonitor()
  432. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  433. let expect = expectation(description: "request should receive appropriate lifetime events")
  434. expect.expectedFulfillmentCount = 2
  435. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  436. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  437. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  438. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  439. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  440. // When
  441. let request = session.request(.default)
  442. for _ in 0..<100 {
  443. request.suspend()
  444. }
  445. waitForExpectations(timeout: timeout)
  446. // Then
  447. XCTAssertEqual(request.state, .suspended)
  448. }
  449. @MainActor
  450. func testThatRequestManuallySuspendedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  451. // Given
  452. let eventMonitor = ClosureEventMonitor()
  453. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  454. let expect = expectation(description: "request should receive appropriate lifetime events")
  455. expect.expectedFulfillmentCount = 2
  456. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  457. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  458. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  459. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  460. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  461. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  462. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  463. // When
  464. let request = session.request(.default)
  465. for _ in 0..<100 {
  466. request.suspend()
  467. }
  468. waitForExpectations(timeout: timeout)
  469. // Then
  470. XCTAssertEqual(request.state, .suspended)
  471. }
  472. @MainActor
  473. func testThatRequestManuallyCancelledManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  474. // Given
  475. let eventMonitor = ClosureEventMonitor()
  476. let session = Session(eventMonitors: [eventMonitor])
  477. let expect = expectation(description: "request should receive appropriate lifetime events")
  478. expect.expectedFulfillmentCount = 2
  479. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  480. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  481. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  482. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  483. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  484. // When
  485. let request = session.request(.default)
  486. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  487. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  488. for _ in 0..<100 {
  489. request.cancel()
  490. }
  491. }
  492. waitForExpectations(timeout: timeout)
  493. // Then
  494. XCTAssertEqual(request.state, .cancelled)
  495. }
  496. @MainActor
  497. func testThatRequestManuallyCancelledManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  498. // Given
  499. let eventMonitor = ClosureEventMonitor()
  500. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  501. let expect = expectation(description: "request should receive appropriate lifetime events")
  502. expect.expectedFulfillmentCount = 2
  503. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  504. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  505. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  506. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  507. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  508. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  509. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  510. // When
  511. let request = session.request(.default)
  512. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  513. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  514. for _ in 0..<100 {
  515. request.cancel()
  516. }
  517. }
  518. waitForExpectations(timeout: timeout)
  519. // Then
  520. XCTAssertEqual(request.state, .cancelled)
  521. }
  522. @MainActor
  523. func testThatRequestManuallyCancelledManyTimesOnManyQueuesOnlyReceivesAppropriateLifetimeEvents() {
  524. // Given
  525. let eventMonitor = ClosureEventMonitor()
  526. let session = Session(eventMonitors: [eventMonitor])
  527. let expect = expectation(description: "request should receive appropriate lifetime events")
  528. expect.expectedFulfillmentCount = 6
  529. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  530. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  531. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  532. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  533. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  534. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  535. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  536. // When
  537. let request = session.request(.delay(5)).response { _ in expect.fulfill() }
  538. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  539. eventMonitor.requestDidCreateTask = { [unowned request] _, _ in
  540. DispatchQueue.concurrentPerform(iterations: 100) { i in
  541. request.cancel()
  542. if i == 99 { expect.fulfill() }
  543. }
  544. }
  545. waitForExpectations(timeout: timeout)
  546. // Then
  547. XCTAssertEqual(request.state, .cancelled)
  548. }
  549. @MainActor
  550. func testThatRequestTriggersAllAppropriateLifetimeEvents() {
  551. // Given
  552. let eventMonitor = ClosureEventMonitor()
  553. let session = Session(eventMonitors: [eventMonitor])
  554. // Disable event test until Firewalk support HTTPS.
  555. // let didReceiveChallenge = expectation(description: "didReceiveChallenge should fire")
  556. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  557. let didReceiveData = expectation(description: "didReceiveData should fire")
  558. let willCacheResponse = expectation(description: "willCacheResponse should fire")
  559. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  560. let didCreateTask = expectation(description: "didCreateTask should fire")
  561. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  562. let didComplete = expectation(description: "didComplete should fire")
  563. let didFinish = expectation(description: "didFinish should fire")
  564. let didResume = expectation(description: "didResume should fire")
  565. let didResumeTask = expectation(description: "didResumeTask should fire")
  566. let didParseResponse = expectation(description: "didParseResponse should fire")
  567. let responseHandler = expectation(description: "responseHandler should fire")
  568. var dataReceived = false
  569. // Disable event test until Firewalk supports HTTPS.
  570. // eventMonitor.taskDidReceiveChallenge = { _, _, _ in didReceiveChallenge.fulfill() }
  571. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  572. eventMonitor.dataTaskDidReceiveData = { _, _, _ in
  573. guard !dataReceived else { return }
  574. // Data may be received many times, fulfill only once.
  575. dataReceived = true
  576. didReceiveData.fulfill()
  577. }
  578. eventMonitor.dataTaskWillCacheResponse = { _, _, _ in willCacheResponse.fulfill() }
  579. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  580. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  581. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  582. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  583. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  584. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  585. eventMonitor.requestDidResumeTask = { _, _ in didResumeTask.fulfill() }
  586. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  587. // When
  588. let request = session.request(.default).response { _ in
  589. responseHandler.fulfill()
  590. }
  591. waitForExpectations(timeout: timeout)
  592. // Then
  593. XCTAssertEqual(request.state, .finished)
  594. }
  595. @MainActor
  596. func testThatCancelledRequestTriggersAllAppropriateLifetimeEvents() {
  597. // Given
  598. let eventMonitor = ClosureEventMonitor()
  599. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  600. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  601. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  602. let didCreateTask = expectation(description: "didCreateTask should fire")
  603. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  604. let didComplete = expectation(description: "didComplete should fire")
  605. let didFinish = expectation(description: "didFinish should fire")
  606. let didResume = expectation(description: "didResume should fire")
  607. let didResumeTask = expectation(description: "didResumeTask should fire")
  608. let didParseResponse = expectation(description: "didParseResponse should fire")
  609. let didCancel = expectation(description: "didCancel should fire")
  610. let didCancelTask = expectation(description: "didCancelTask should fire")
  611. let responseHandler = expectation(description: "responseHandler should fire")
  612. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  613. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  614. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  615. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  616. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  617. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  618. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  619. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  620. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  621. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  622. // When
  623. let request = session.request(.delay(5)).response { _ in
  624. responseHandler.fulfill()
  625. }
  626. eventMonitor.requestDidResumeTask = { [unowned request] _, _ in
  627. request.cancel()
  628. didResumeTask.fulfill()
  629. }
  630. request.resume()
  631. waitForExpectations(timeout: timeout)
  632. // Then
  633. XCTAssertEqual(request.state, .cancelled)
  634. }
  635. @MainActor
  636. func testThatAppendingResponseSerializerToCancelledRequestCallsCompletion() {
  637. // Given
  638. let session = Session()
  639. var response1: DataResponse<TestResponse, AFError>?
  640. var response2: DataResponse<TestResponse, AFError>?
  641. let expect = expectation(description: "both response serializer completions should be called")
  642. expect.expectedFulfillmentCount = 2
  643. // When
  644. let request = session.request(.default)
  645. request.responseDecodable(of: TestResponse.self) { resp in
  646. response1 = resp
  647. expect.fulfill()
  648. request.responseDecodable(of: TestResponse.self) { resp in
  649. response2 = resp
  650. expect.fulfill()
  651. }
  652. }
  653. request.cancel()
  654. waitForExpectations(timeout: timeout)
  655. // Then
  656. XCTAssertEqual(response1?.error?.isExplicitlyCancelledError, true)
  657. XCTAssertEqual(response2?.error?.isExplicitlyCancelledError, true)
  658. }
  659. @MainActor
  660. func testThatAppendingResponseSerializerToCompletedRequestInsideCompletionResumesRequest() {
  661. // Given
  662. let session = Session()
  663. var response1: DataResponse<TestResponse, AFError>?
  664. var response2: DataResponse<TestResponse, AFError>?
  665. var response3: DataResponse<TestResponse, AFError>?
  666. let expect = expectation(description: "all response serializer completions should be called")
  667. expect.expectedFulfillmentCount = 3
  668. // When
  669. let request = session.request(.default)
  670. request.responseDecodable(of: TestResponse.self) { resp in
  671. response1 = resp
  672. expect.fulfill()
  673. request.responseDecodable(of: TestResponse.self) { resp in
  674. response2 = resp
  675. expect.fulfill()
  676. request.responseDecodable(of: TestResponse.self) { resp in
  677. response3 = resp
  678. expect.fulfill()
  679. }
  680. }
  681. }
  682. waitForExpectations(timeout: timeout)
  683. // Then
  684. XCTAssertNotNil(response1?.value)
  685. XCTAssertNotNil(response2?.value)
  686. XCTAssertNotNil(response3?.value)
  687. }
  688. @MainActor
  689. func testThatAppendingResponseSerializerToCompletedRequestOutsideCompletionResumesRequest() {
  690. // Given
  691. let session = Session()
  692. let request = session.request(.default)
  693. var response1: DataResponse<TestResponse, AFError>?
  694. var response2: DataResponse<TestResponse, AFError>?
  695. var response3: DataResponse<TestResponse, AFError>?
  696. // When
  697. let expect1 = expectation(description: "response serializer 1 completion should be called")
  698. request.responseDecodable(of: TestResponse.self) { response1 = $0; expect1.fulfill() }
  699. waitForExpectations(timeout: timeout)
  700. let expect2 = expectation(description: "response serializer 2 completion should be called")
  701. request.responseDecodable(of: TestResponse.self) { response2 = $0; expect2.fulfill() }
  702. waitForExpectations(timeout: timeout)
  703. let expect3 = expectation(description: "response serializer 3 completion should be called")
  704. request.responseDecodable(of: TestResponse.self) { response3 = $0; expect3.fulfill() }
  705. waitForExpectations(timeout: timeout)
  706. // Then
  707. XCTAssertNotNil(response1?.value)
  708. XCTAssertNotNil(response2?.value)
  709. XCTAssertNotNil(response3?.value)
  710. }
  711. }
  712. // MARK: -
  713. final class RequestDescriptionTestCase: BaseTestCase {
  714. @MainActor
  715. func testRequestDescription() {
  716. // Given
  717. let url = Endpoint().url
  718. let manager = Session(startRequestsImmediately: false)
  719. let request = manager.request(url)
  720. let expectation = expectation(description: "Request description should update: \(url)")
  721. var response: HTTPURLResponse?
  722. // When
  723. request.response { resp in
  724. response = resp.response
  725. expectation.fulfill()
  726. }.resume()
  727. waitForExpectations(timeout: timeout)
  728. // Then
  729. XCTAssertEqual(request.description, "GET \(url) (\(response?.statusCode ?? -1))")
  730. }
  731. }
  732. // MARK: -
  733. final class RequestCURLDescriptionTestCase: BaseTestCase {
  734. // MARK: Properties
  735. let session: Session = {
  736. let manager = Session()
  737. return manager
  738. }()
  739. let sessionWithAcceptLanguageHeader: Session = {
  740. var headers = HTTPHeaders.default
  741. headers["Accept-Language"] = "en-US"
  742. let configuration = URLSessionConfiguration.af.default
  743. configuration.headers = headers
  744. let manager = Session(configuration: configuration)
  745. return manager
  746. }()
  747. let sessionWithContentTypeHeader: Session = {
  748. var headers = HTTPHeaders.default
  749. headers["Content-Type"] = "application/json"
  750. let configuration = URLSessionConfiguration.af.default
  751. configuration.headers = headers
  752. let manager = Session(configuration: configuration)
  753. return manager
  754. }()
  755. func sessionWithCookie(_ cookie: HTTPCookie) -> Session {
  756. let configuration = URLSessionConfiguration.af.default
  757. configuration.httpCookieStorage?.setCookie(cookie)
  758. return Session(configuration: configuration)
  759. }
  760. let sessionDisallowingCookies: Session = {
  761. let configuration = URLSessionConfiguration.af.default
  762. configuration.httpShouldSetCookies = false
  763. let manager = Session(configuration: configuration)
  764. return manager
  765. }()
  766. // MARK: Tests
  767. @MainActor
  768. func testGETRequestCURLDescription() {
  769. // Given
  770. let url = Endpoint().url
  771. let expectation = expectation(description: "request should complete")
  772. var components: [String]?
  773. // When
  774. session.request(url).cURLDescription {
  775. components = self.cURLCommandComponents(from: $0)
  776. expectation.fulfill()
  777. }
  778. waitForExpectations(timeout: timeout)
  779. // Then
  780. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  781. XCTAssertTrue(components?.contains("-X") == true)
  782. XCTAssertEqual(components?.last, "\"\(url)\"")
  783. }
  784. @MainActor
  785. func testGETRequestCURLDescriptionOnMainQueue() {
  786. // Given
  787. let url = Endpoint().url
  788. let expectation = expectation(description: "request should complete")
  789. var isMainThread = false
  790. var components: [String]?
  791. // When
  792. session.request(url).cURLDescription(on: .main) {
  793. components = self.cURLCommandComponents(from: $0)
  794. isMainThread = Thread.isMainThread
  795. expectation.fulfill()
  796. }
  797. waitForExpectations(timeout: timeout, handler: nil)
  798. // Then
  799. XCTAssertTrue(isMainThread)
  800. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  801. XCTAssertTrue(components?.contains("-X") == true)
  802. XCTAssertEqual(components?.last, "\"\(url)\"")
  803. }
  804. @MainActor
  805. func testGETRequestCURLDescriptionSynchronous() {
  806. // Given
  807. let url = Endpoint().url
  808. let expectation = expectation(description: "request should complete")
  809. var components: [String]?
  810. var syncComponents: [String]?
  811. // When
  812. let request = session.request(url)
  813. request.cURLDescription {
  814. components = self.cURLCommandComponents(from: $0)
  815. syncComponents = self.cURLCommandComponents(from: request.cURLDescription())
  816. expectation.fulfill()
  817. }
  818. waitForExpectations(timeout: timeout)
  819. // Then
  820. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  821. XCTAssertTrue(components?.contains("-X") == true)
  822. XCTAssertEqual(components?.last, "\"\(url)\"")
  823. XCTAssertEqual(components?.sorted(), syncComponents?.sorted())
  824. }
  825. @MainActor
  826. func testGETRequestCURLDescriptionCanBeRequestedManyTimes() {
  827. // Given
  828. let url = Endpoint().url
  829. let expectation = expectation(description: "request should complete")
  830. var components: [String]?
  831. var secondComponents: [String]?
  832. // When
  833. let request = session.request(url)
  834. request.cURLDescription {
  835. components = self.cURLCommandComponents(from: $0)
  836. request.cURLDescription {
  837. secondComponents = self.cURLCommandComponents(from: $0)
  838. expectation.fulfill()
  839. }
  840. }
  841. waitForExpectations(timeout: timeout)
  842. // Then
  843. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  844. XCTAssertTrue(components?.contains("-X") == true)
  845. XCTAssertEqual(components?.last, "\"\(url)\"")
  846. XCTAssertEqual(components?.sorted(), secondComponents?.sorted())
  847. }
  848. @MainActor
  849. func testGETRequestWithCustomHeaderCURLDescription() {
  850. // Given
  851. let url = Endpoint().url
  852. let expectation = expectation(description: "request should complete")
  853. var cURLDescription: String?
  854. // When
  855. let headers: HTTPHeaders = ["X-Custom-Header": "{\"key\": \"value\"}"]
  856. session.request(url, headers: headers).cURLDescription {
  857. cURLDescription = $0
  858. expectation.fulfill()
  859. }
  860. waitForExpectations(timeout: timeout)
  861. // Then
  862. XCTAssertNotNil(cURLDescription?.range(of: "-H \"X-Custom-Header: {\\\"key\\\": \\\"value\\\"}\""))
  863. }
  864. @MainActor
  865. func testGETRequestWithDuplicateHeadersDebugDescription() {
  866. // Given
  867. let url = Endpoint().url
  868. let expectation = expectation(description: "request should complete")
  869. var cURLDescription: String?
  870. var components: [String]?
  871. // When
  872. let headers: HTTPHeaders = ["Accept-Language": "en-GB"]
  873. sessionWithAcceptLanguageHeader.request(url, headers: headers).cURLDescription {
  874. components = self.cURLCommandComponents(from: $0)
  875. cURLDescription = $0
  876. expectation.fulfill()
  877. }
  878. waitForExpectations(timeout: timeout)
  879. // Then
  880. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  881. XCTAssertTrue(components?.contains("-X") == true)
  882. XCTAssertEqual(components?.last, "\"\(url)\"")
  883. let acceptLanguageCount = components?.filter { $0.contains("Accept-Language") }.count
  884. XCTAssertEqual(acceptLanguageCount, 1, "command should contain a single Accept-Language header")
  885. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Accept-Language: en-GB\""))
  886. }
  887. @MainActor
  888. func testPOSTRequestCURLDescription() {
  889. // Given
  890. let url = Endpoint.method(.post).url
  891. let expectation = expectation(description: "request should complete")
  892. var components: [String]?
  893. // When
  894. session.request(url, method: .post).cURLDescription {
  895. components = self.cURLCommandComponents(from: $0)
  896. expectation.fulfill()
  897. }
  898. waitForExpectations(timeout: timeout)
  899. // Then
  900. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  901. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  902. XCTAssertEqual(components?.last, "\"\(url)\"")
  903. }
  904. @MainActor
  905. func testPOSTRequestWithJSONParametersCURLDescription() {
  906. // Given
  907. let url = Endpoint.method(.post).url
  908. let expectation = expectation(description: "request should complete")
  909. var cURLDescription: String?
  910. var components: [String]?
  911. let parameters = ["foo": "bar",
  912. "fo\"o": "b\"ar",
  913. "f'oo": "ba'r"]
  914. // When
  915. session.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).cURLDescription {
  916. components = self.cURLCommandComponents(from: $0)
  917. cURLDescription = $0
  918. expectation.fulfill()
  919. }
  920. waitForExpectations(timeout: timeout)
  921. // Then
  922. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  923. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  924. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: application/json\""))
  925. XCTAssertNotNil(cURLDescription?.range(of: "-d \"{"))
  926. XCTAssertNotNil(cURLDescription?.range(of: "\\\"f'oo\\\":\\\"ba'r\\\""))
  927. XCTAssertNotNil(cURLDescription?.range(of: "\\\"fo\\\\\\\"o\\\":\\\"b\\\\\\\"ar\\\""))
  928. XCTAssertNotNil(cURLDescription?.range(of: "\\\"foo\\\":\\\"bar\\"))
  929. XCTAssertEqual(components?.last, "\"\(url)\"")
  930. }
  931. @MainActor
  932. func testPOSTRequestWithCookieCURLDescription() {
  933. // Given
  934. let url = Endpoint.method(.post).url
  935. let cookie = HTTPCookie(properties: [.domain: url.host as Any,
  936. .path: url.path,
  937. .name: "foo",
  938. .value: "bar"])!
  939. let cookieManager = sessionWithCookie(cookie)
  940. let expectation = expectation(description: "request should complete")
  941. var components: [String]?
  942. // When
  943. cookieManager.request(url, method: .post).cURLDescription {
  944. components = self.cURLCommandComponents(from: $0)
  945. expectation.fulfill()
  946. }
  947. waitForExpectations(timeout: timeout)
  948. // Then
  949. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  950. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  951. XCTAssertEqual(components?.last, "\"\(url)\"")
  952. XCTAssertEqual(components?[5..<6], ["-b"])
  953. }
  954. @MainActor
  955. func testPOSTRequestWithCookiesDisabledCURLDescriptionHasNoCookies() {
  956. // Given
  957. let url = Endpoint.method(.post).url
  958. let cookie = HTTPCookie(properties: [.domain: url.host as Any,
  959. .path: url.path,
  960. .name: "foo",
  961. .value: "bar"])!
  962. sessionDisallowingCookies.session.configuration.httpCookieStorage?.setCookie(cookie)
  963. let expectation = expectation(description: "request should complete")
  964. var components: [String]?
  965. // When
  966. sessionDisallowingCookies.request(url, method: .post).cURLDescription {
  967. components = self.cURLCommandComponents(from: $0)
  968. expectation.fulfill()
  969. }
  970. waitForExpectations(timeout: timeout)
  971. // Then
  972. let cookieComponents = components?.filter { $0 == "-b" }
  973. XCTAssertTrue(cookieComponents?.isEmpty == true)
  974. }
  975. @MainActor
  976. func testMultipartFormDataRequestWithDuplicateHeadersCURLDescriptionHasOneContentTypeHeader() {
  977. // Given
  978. let url = Endpoint.method(.post).url
  979. let japaneseData = Data("日本語".utf8)
  980. let expectation = expectation(description: "multipart form data encoding should succeed")
  981. var cURLDescription: String?
  982. var components: [String]?
  983. // When
  984. sessionWithContentTypeHeader.upload(multipartFormData: { data in
  985. data.append(japaneseData, withName: "japanese")
  986. }, to: url).cURLDescription {
  987. components = self.cURLCommandComponents(from: $0)
  988. cURLDescription = $0
  989. expectation.fulfill()
  990. }
  991. waitForExpectations(timeout: timeout)
  992. // Then
  993. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  994. XCTAssertTrue(components?.contains("-X") == true)
  995. XCTAssertEqual(components?.last, "\"\(url)\"")
  996. let contentTypeCount = components?.filter { $0.contains("Content-Type") }.count
  997. XCTAssertEqual(contentTypeCount, 1, "command should contain a single Content-Type header")
  998. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: multipart/form-data;"))
  999. }
  1000. @MainActor
  1001. func testThatRequestWithInvalidURLDebugDescription() {
  1002. // Given
  1003. let urlString = "invalid_url"
  1004. let expectation = expectation(description: "request should complete")
  1005. var cURLDescription: String?
  1006. // When
  1007. session.request(urlString).cURLDescription {
  1008. cURLDescription = $0
  1009. expectation.fulfill()
  1010. }
  1011. waitForExpectations(timeout: timeout)
  1012. // Then
  1013. XCTAssertNotNil(cURLDescription, "debugDescription should not crash")
  1014. }
  1015. // MARK: Test Helper Methods
  1016. private func cURLCommandComponents(from cURLString: String) -> [String] {
  1017. cURLString.components(separatedBy: .whitespacesAndNewlines)
  1018. .filter { $0 != "" && $0 != "\\" }
  1019. }
  1020. }
  1021. final class RequestLifetimeTests: BaseTestCase {
  1022. @MainActor
  1023. func testThatRequestProvidesURLRequestWhenCreated() {
  1024. // Given
  1025. let didReceiveRequest = expectation(description: "did receive task")
  1026. let didComplete = expectation(description: "request did complete")
  1027. var request: URLRequest?
  1028. // When
  1029. AF.request(.default)
  1030. .onURLRequestCreation { request = $0; didReceiveRequest.fulfill() }
  1031. .responseDecodable(of: TestResponse.self) { _ in didComplete.fulfill() }
  1032. wait(for: [didReceiveRequest, didComplete], timeout: timeout, enforceOrder: true)
  1033. // Then
  1034. XCTAssertNotNil(request)
  1035. }
  1036. @MainActor
  1037. func testThatRequestProvidesTaskWhenCreated() {
  1038. // Given
  1039. let didReceiveTask = expectation(description: "did receive task")
  1040. let didComplete = expectation(description: "request did complete")
  1041. var task: URLSessionTask?
  1042. // When
  1043. AF.request(.default)
  1044. .onURLSessionTaskCreation { task = $0; didReceiveTask.fulfill() }
  1045. .responseDecodable(of: TestResponse.self) { _ in didComplete.fulfill() }
  1046. wait(for: [didReceiveTask, didComplete], timeout: timeout, enforceOrder: true)
  1047. // Then
  1048. XCTAssertNotNil(task)
  1049. }
  1050. }
  1051. // MARK: -
  1052. final class RequestInvalidURLTestCase: BaseTestCase {
  1053. @MainActor
  1054. func testThatDataRequestWithFileURLThrowsError() {
  1055. // Given
  1056. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1057. let expectation = expectation(description: "Request should succeed.")
  1058. var response: DataResponse<Data?, AFError>?
  1059. // When
  1060. AF.request(fileURL)
  1061. .response { resp in
  1062. response = resp
  1063. expectation.fulfill()
  1064. }
  1065. waitForExpectations(timeout: timeout)
  1066. // Then
  1067. XCTAssertEqual(response?.result.isSuccess, true)
  1068. }
  1069. @MainActor
  1070. func testThatDownloadRequestWithFileURLThrowsError() {
  1071. // Given
  1072. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1073. let expectation = expectation(description: "Request should succeed.")
  1074. var response: DownloadResponse<URL?, AFError>?
  1075. // When
  1076. AF.download(fileURL)
  1077. .response { resp in
  1078. response = resp
  1079. expectation.fulfill()
  1080. }
  1081. waitForExpectations(timeout: timeout)
  1082. // Then
  1083. XCTAssertEqual(response?.result.isSuccess, true)
  1084. }
  1085. @MainActor
  1086. func testThatDataStreamRequestWithFileURLThrowsError() {
  1087. // Given
  1088. let fileURL = url(forResource: "valid_data", withExtension: "json")
  1089. let expectation = expectation(description: "Request should succeed.")
  1090. var response: DataStreamRequest.Completion?
  1091. // When
  1092. AF.streamRequest(fileURL)
  1093. .responseStream { stream in
  1094. guard case let .complete(completion) = stream.event else { return }
  1095. response = completion
  1096. expectation.fulfill()
  1097. }
  1098. waitForExpectations(timeout: timeout)
  1099. // Then
  1100. XCTAssertNil(response?.response)
  1101. }
  1102. }
  1103. #if canImport(zlib) && !os(Android) // Same condition as `DeflateRequestCompressor`.
  1104. @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
  1105. final class RequestCompressionTests: BaseTestCase {
  1106. func testThatRequestsCanBeCompressed() async {
  1107. // Given
  1108. let url = Endpoint.method(.post).url
  1109. let parameters = TestParameters(property: "compressed")
  1110. // When
  1111. let result = await AF.request(url,
  1112. method: .post,
  1113. parameters: parameters,
  1114. encoder: .json,
  1115. interceptor: .deflateCompressor)
  1116. .serializingDecodable(TestResponse.self)
  1117. .result
  1118. // Then
  1119. XCTAssertTrue(result.isSuccess)
  1120. }
  1121. func testThatDeflateCompressorThrowsErrorByDefaultWhenRequestAlreadyHasHeader() async {
  1122. // Given
  1123. let url = Endpoint.method(.post).url
  1124. let parameters = TestParameters(property: "compressed")
  1125. // When
  1126. let result = await AF.request(url,
  1127. method: .post,
  1128. parameters: parameters,
  1129. encoder: .json,
  1130. headers: [.contentEncoding("value")],
  1131. interceptor: .deflateCompressor)
  1132. .serializingDecodable(TestResponse.self)
  1133. .result
  1134. // Then
  1135. XCTAssertFalse(result.isSuccess)
  1136. XCTAssertNotNil(result.failure?.underlyingError as? DeflateRequestCompressor.DuplicateHeaderError)
  1137. }
  1138. func testThatDeflateCompressorThrowsErrorWhenConfigured() async {
  1139. // Given
  1140. let url = Endpoint.method(.post).url
  1141. let parameters = TestParameters(property: "compressed")
  1142. // When
  1143. let result = await AF.request(url,
  1144. method: .post,
  1145. parameters: parameters,
  1146. encoder: .json,
  1147. headers: [.contentEncoding("value")],
  1148. interceptor: .deflateCompressor(duplicateHeaderBehavior: .error))
  1149. .serializingDecodable(TestResponse.self)
  1150. .result
  1151. // Then
  1152. XCTAssertFalse(result.isSuccess)
  1153. XCTAssertNotNil(result.failure?.underlyingError as? DeflateRequestCompressor.DuplicateHeaderError)
  1154. }
  1155. func testThatDeflateCompressorReplacesHeaderWhenConfigured() async {
  1156. // Given
  1157. let url = Endpoint.method(.post).url
  1158. let parameters = TestParameters(property: "compressed")
  1159. // When
  1160. let result = await AF.request(url,
  1161. method: .post,
  1162. parameters: parameters,
  1163. encoder: .json,
  1164. headers: [.contentEncoding("value")],
  1165. interceptor: .deflateCompressor(duplicateHeaderBehavior: .replace))
  1166. .serializingDecodable(TestResponse.self)
  1167. .result
  1168. // Then
  1169. XCTAssertTrue(result.isSuccess)
  1170. }
  1171. func testThatDeflateCompressorSkipsCompressionWhenConfigured() async {
  1172. // Given
  1173. let url = Endpoint.method(.post).url
  1174. let parameters = TestParameters(property: "compressed")
  1175. // When
  1176. let result = await AF.request(url,
  1177. method: .post,
  1178. parameters: parameters,
  1179. encoder: .json,
  1180. headers: [.contentEncoding("gzip")],
  1181. interceptor: .deflateCompressor(duplicateHeaderBehavior: .skip))
  1182. .serializingDecodable(TestResponse.self)
  1183. .result
  1184. // Then
  1185. // Request fails as the server expects gzip compression.
  1186. XCTAssertFalse(result.isSuccess)
  1187. }
  1188. func testThatDeflateCompressorDoesNotCompressDataWhenClosureReturnsFalse() async {
  1189. // Given
  1190. let url = Endpoint.method(.post).url
  1191. let parameters = TestParameters(property: "compressed")
  1192. // When
  1193. let result = await AF.request(url,
  1194. method: .post,
  1195. parameters: parameters,
  1196. encoder: .json,
  1197. interceptor: .deflateCompressor { _ in false })
  1198. .serializingDecodable(TestResponse.self)
  1199. .result
  1200. // Then
  1201. XCTAssertTrue(result.isSuccess)
  1202. // With no compression, request headers reflected from server should have no Content-Encoding.
  1203. XCTAssertNil(result.success?.headers["Content-Encoding"])
  1204. }
  1205. }
  1206. #endif