RequestTests.swift 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. //
  2. // RequestTests.swift
  3. //
  4. // Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. import Alamofire
  25. import Foundation
  26. import XCTest
  27. final class RequestResponseTestCase: BaseTestCase {
  28. func testRequestResponse() {
  29. // Given
  30. let urlString = "https://httpbin.org/get"
  31. let expectation = self.expectation(description: "GET request should succeed: \(urlString)")
  32. var response: DataResponse<Data?, AFError>?
  33. // When
  34. AF.request(urlString, parameters: ["foo": "bar"])
  35. .response { resp in
  36. response = resp
  37. expectation.fulfill()
  38. }
  39. waitForExpectations(timeout: timeout, handler: nil)
  40. // Then
  41. XCTAssertNotNil(response?.request)
  42. XCTAssertNotNil(response?.response)
  43. XCTAssertNotNil(response?.data)
  44. XCTAssertNil(response?.error)
  45. }
  46. func testRequestResponseWithProgress() {
  47. // Given
  48. let randomBytes = 1 * 25 * 1024
  49. let urlString = "https://httpbin.org/bytes/\(randomBytes)"
  50. let expectation = self.expectation(description: "Bytes download progress should be reported: \(urlString)")
  51. var progressValues: [Double] = []
  52. var response: DataResponse<Data?, AFError>?
  53. // When
  54. AF.request(urlString)
  55. .downloadProgress { progress in
  56. progressValues.append(progress.fractionCompleted)
  57. }
  58. .response { resp in
  59. response = resp
  60. expectation.fulfill()
  61. }
  62. waitForExpectations(timeout: timeout, handler: nil)
  63. // Then
  64. XCTAssertNotNil(response?.request)
  65. XCTAssertNotNil(response?.response)
  66. XCTAssertNotNil(response?.data)
  67. XCTAssertNil(response?.error)
  68. var previousProgress: Double = progressValues.first ?? 0.0
  69. for progress in progressValues {
  70. XCTAssertGreaterThanOrEqual(progress, previousProgress)
  71. previousProgress = progress
  72. }
  73. if let lastProgressValue = progressValues.last {
  74. XCTAssertEqual(lastProgressValue, 1.0)
  75. } else {
  76. XCTFail("last item in progressValues should not be nil")
  77. }
  78. }
  79. func testPOSTRequestWithUnicodeParameters() {
  80. // Given
  81. let urlString = "https://httpbin.org/post"
  82. let parameters = ["french": "français",
  83. "japanese": "日本語",
  84. "arabic": "العربية",
  85. "emoji": "😃"]
  86. let expectation = self.expectation(description: "request should succeed")
  87. var response: DataResponse<Any, AFError>?
  88. // When
  89. AF.request(urlString, method: .post, parameters: parameters)
  90. .responseJSON { closureResponse in
  91. response = closureResponse
  92. expectation.fulfill()
  93. }
  94. waitForExpectations(timeout: timeout, handler: nil)
  95. // Then
  96. XCTAssertNotNil(response?.request)
  97. XCTAssertNotNil(response?.response)
  98. XCTAssertNotNil(response?.data)
  99. if let json = response?.result.success as? [String: Any], let form = json["form"] as? [String: String] {
  100. XCTAssertEqual(form["french"], parameters["french"])
  101. XCTAssertEqual(form["japanese"], parameters["japanese"])
  102. XCTAssertEqual(form["arabic"], parameters["arabic"])
  103. XCTAssertEqual(form["emoji"], parameters["emoji"])
  104. } else {
  105. XCTFail("form parameter in JSON should not be nil")
  106. }
  107. }
  108. func testPOSTRequestWithBase64EncodedImages() {
  109. // Given
  110. let urlString = "https://httpbin.org/post"
  111. let pngBase64EncodedString: String = {
  112. let URL = url(forResource: "unicorn", withExtension: "png")
  113. let data = try! Data(contentsOf: URL)
  114. return data.base64EncodedString(options: .lineLength64Characters)
  115. }()
  116. let jpegBase64EncodedString: String = {
  117. let URL = url(forResource: "rainbow", withExtension: "jpg")
  118. let data = try! Data(contentsOf: URL)
  119. return data.base64EncodedString(options: .lineLength64Characters)
  120. }()
  121. let parameters = ["email": "user@alamofire.org",
  122. "png_image": pngBase64EncodedString,
  123. "jpeg_image": jpegBase64EncodedString]
  124. let expectation = self.expectation(description: "request should succeed")
  125. var response: DataResponse<Any, AFError>?
  126. // When
  127. AF.request(urlString, method: .post, parameters: parameters)
  128. .responseJSON { closureResponse in
  129. response = closureResponse
  130. expectation.fulfill()
  131. }
  132. waitForExpectations(timeout: timeout, handler: nil)
  133. // Then
  134. XCTAssertNotNil(response?.request)
  135. XCTAssertNotNil(response?.response)
  136. XCTAssertNotNil(response?.data)
  137. XCTAssertEqual(response?.result.isSuccess, true)
  138. if let json = response?.result.success as? [String: Any], let form = json["form"] as? [String: String] {
  139. XCTAssertEqual(form["email"], parameters["email"])
  140. XCTAssertEqual(form["png_image"], parameters["png_image"])
  141. XCTAssertEqual(form["jpeg_image"], parameters["jpeg_image"])
  142. } else {
  143. XCTFail("form parameter in JSON should not be nil")
  144. }
  145. }
  146. // MARK: Queues
  147. func testThatResponseSerializationWorksWithSerializationQueue() {
  148. // Given
  149. let queue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  150. let manager = Session(serializationQueue: queue)
  151. let expectation = self.expectation(description: "request should complete")
  152. var response: DataResponse<Any, AFError>?
  153. // When
  154. manager.request("https://httpbin.org/get").responseJSON { resp in
  155. response = resp
  156. expectation.fulfill()
  157. }
  158. waitForExpectations(timeout: timeout, handler: nil)
  159. // Then
  160. XCTAssertEqual(response?.result.isSuccess, true)
  161. }
  162. func testThatRequestsWorksWithRequestAndSerializationQueue() {
  163. // Given
  164. let requestQueue = DispatchQueue(label: "org.alamofire.testRequestQueue")
  165. let serializationQueue = DispatchQueue(label: "org.alamofire.testSerializationQueue")
  166. let manager = Session(requestQueue: requestQueue, serializationQueue: serializationQueue)
  167. let expectation = self.expectation(description: "request should complete")
  168. var response: DataResponse<Any, AFError>?
  169. // When
  170. manager.request("https://httpbin.org/get").responseJSON { resp in
  171. response = resp
  172. expectation.fulfill()
  173. }
  174. waitForExpectations(timeout: timeout, handler: nil)
  175. // Then
  176. XCTAssertEqual(response?.result.isSuccess, true)
  177. }
  178. // MARK: Encodable Parameters
  179. func testThatRequestsCanPassEncodableParametersAsJSONBodyData() {
  180. // Given
  181. let parameters = HTTPBinParameters(property: "one")
  182. let expect = expectation(description: "request should complete")
  183. var receivedResponse: DataResponse<HTTPBinResponse, AFError>?
  184. // When
  185. AF.request("https://httpbin.org/post", method: .post, parameters: parameters, encoder: JSONParameterEncoder.default)
  186. .responseDecodable(of: HTTPBinResponse.self) { response in
  187. receivedResponse = response
  188. expect.fulfill()
  189. }
  190. waitForExpectations(timeout: timeout, handler: nil)
  191. // Then
  192. XCTAssertEqual(receivedResponse?.result.success?.data, "{\"property\":\"one\"}")
  193. }
  194. func testThatRequestsCanPassEncodableParametersAsAURLQuery() {
  195. // Given
  196. let parameters = HTTPBinParameters(property: "one")
  197. let expect = expectation(description: "request should complete")
  198. var receivedResponse: DataResponse<HTTPBinResponse, AFError>?
  199. // When
  200. AF.request("https://httpbin.org/get", method: .get, parameters: parameters)
  201. .responseDecodable(of: HTTPBinResponse.self) { response in
  202. receivedResponse = response
  203. expect.fulfill()
  204. }
  205. waitForExpectations(timeout: timeout, handler: nil)
  206. // Then
  207. XCTAssertEqual(receivedResponse?.result.success?.args, ["property": "one"])
  208. }
  209. func testThatRequestsCanPassEncodableParametersAsURLEncodedBodyData() {
  210. // Given
  211. let parameters = HTTPBinParameters(property: "one")
  212. let expect = expectation(description: "request should complete")
  213. var receivedResponse: DataResponse<HTTPBinResponse, AFError>?
  214. // When
  215. AF.request("https://httpbin.org/post", method: .post, parameters: parameters)
  216. .responseDecodable(of: HTTPBinResponse.self) { response in
  217. receivedResponse = response
  218. expect.fulfill()
  219. }
  220. waitForExpectations(timeout: timeout, handler: nil)
  221. // Then
  222. XCTAssertEqual(receivedResponse?.result.success?.form, ["property": "one"])
  223. }
  224. // MARK: Lifetime Events
  225. func testThatAutomaticallyResumedRequestReceivesAppropriateLifetimeEvents() {
  226. // Given
  227. let eventMonitor = ClosureEventMonitor()
  228. let session = Session(eventMonitors: [eventMonitor])
  229. let expect = expectation(description: "request should receive appropriate lifetime events")
  230. expect.expectedFulfillmentCount = 4
  231. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  232. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  233. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  234. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  235. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  236. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  237. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  238. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  239. // When
  240. let request = session.request(URLRequest.makeHTTPBinRequest()).response { _ in expect.fulfill() }
  241. waitForExpectations(timeout: timeout, handler: nil)
  242. // Then
  243. XCTAssertEqual(request.state, .finished)
  244. }
  245. func testThatAutomaticallyAndManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  246. // Given
  247. let eventMonitor = ClosureEventMonitor()
  248. let session = Session(eventMonitors: [eventMonitor])
  249. let expect = expectation(description: "request should receive appropriate lifetime events")
  250. expect.expectedFulfillmentCount = 3
  251. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  252. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  253. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  254. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  255. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  256. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  257. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  258. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  259. // When
  260. let request = session.request(URLRequest.makeHTTPBinRequest())
  261. for _ in 0..<100 {
  262. request.resume()
  263. }
  264. waitForExpectations(timeout: timeout, handler: nil)
  265. // Then
  266. XCTAssertEqual(request.state, .finished)
  267. }
  268. func testThatManuallyResumedRequestReceivesAppropriateLifetimeEvents() {
  269. // Given
  270. let eventMonitor = ClosureEventMonitor()
  271. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  272. let expect = expectation(description: "request should receive appropriate lifetime events")
  273. expect.expectedFulfillmentCount = 3
  274. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  275. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  276. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  277. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  278. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  279. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  280. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  281. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  282. // When
  283. let request = session.request(URLRequest.makeHTTPBinRequest())
  284. for _ in 0..<100 {
  285. request.resume()
  286. }
  287. waitForExpectations(timeout: timeout, handler: nil)
  288. // Then
  289. XCTAssertEqual(request.state, .finished)
  290. }
  291. func testThatRequestManuallyResumedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  292. // Given
  293. let eventMonitor = ClosureEventMonitor()
  294. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  295. let expect = expectation(description: "request should receive appropriate lifetime events")
  296. expect.expectedFulfillmentCount = 3
  297. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  298. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  299. eventMonitor.requestDidFinish = { _ in expect.fulfill() }
  300. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  301. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  302. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  303. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  304. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  305. // When
  306. let request = session.request(URLRequest.makeHTTPBinRequest())
  307. for _ in 0..<100 {
  308. request.resume()
  309. }
  310. waitForExpectations(timeout: timeout, handler: nil)
  311. // Then
  312. XCTAssertEqual(request.state, .finished)
  313. }
  314. func testThatRequestManuallySuspendedManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  315. // Given
  316. let eventMonitor = ClosureEventMonitor()
  317. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  318. let expect = expectation(description: "request should receive appropriate lifetime events")
  319. expect.expectedFulfillmentCount = 2
  320. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  321. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  322. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  323. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  324. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  325. // When
  326. let request = session.request(URLRequest.makeHTTPBinRequest())
  327. for _ in 0..<100 {
  328. request.suspend()
  329. }
  330. waitForExpectations(timeout: timeout, handler: nil)
  331. // Then
  332. XCTAssertEqual(request.state, .suspended)
  333. }
  334. func testThatRequestManuallySuspendedManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  335. // Given
  336. let eventMonitor = ClosureEventMonitor()
  337. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  338. let expect = expectation(description: "request should receive appropriate lifetime events")
  339. expect.expectedFulfillmentCount = 2
  340. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  341. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  342. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  343. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  344. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  345. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  346. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  347. // When
  348. let request = session.request(URLRequest.makeHTTPBinRequest())
  349. for _ in 0..<100 {
  350. request.suspend()
  351. }
  352. waitForExpectations(timeout: timeout, handler: nil)
  353. // Then
  354. XCTAssertEqual(request.state, .suspended)
  355. }
  356. func testThatRequestManuallyCancelledManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents() {
  357. // Given
  358. let eventMonitor = ClosureEventMonitor()
  359. let session = Session(eventMonitors: [eventMonitor])
  360. let expect = expectation(description: "request should receive appropriate lifetime events")
  361. expect.expectedFulfillmentCount = 2
  362. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  363. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  364. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  365. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  366. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  367. // When
  368. let request = session.request(URLRequest.makeHTTPBinRequest())
  369. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  370. eventMonitor.requestDidCreateTask = { _, _ in
  371. for _ in 0..<100 {
  372. request.cancel()
  373. }
  374. }
  375. waitForExpectations(timeout: timeout, handler: nil)
  376. // Then
  377. XCTAssertEqual(request.state, .cancelled)
  378. }
  379. func testThatRequestManuallyCancelledManyTimesOnlyReceivesAppropriateLifetimeEvents() {
  380. // Given
  381. let eventMonitor = ClosureEventMonitor()
  382. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  383. let expect = expectation(description: "request should receive appropriate lifetime events")
  384. expect.expectedFulfillmentCount = 2
  385. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  386. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  387. // Fulfill other events that would exceed the expected count. Inverted expectations require the full timeout.
  388. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  389. eventMonitor.requestDidResumeTask = { _, _ in expect.fulfill() }
  390. eventMonitor.requestDidSuspend = { _ in expect.fulfill() }
  391. eventMonitor.requestDidSuspendTask = { _, _ in expect.fulfill() }
  392. // When
  393. let request = session.request(URLRequest.makeHTTPBinRequest())
  394. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  395. eventMonitor.requestDidCreateTask = { _, _ in
  396. for _ in 0..<100 {
  397. request.cancel()
  398. }
  399. }
  400. waitForExpectations(timeout: timeout, handler: nil)
  401. // Then
  402. XCTAssertEqual(request.state, .cancelled)
  403. }
  404. func testThatRequestManuallyCancelledManyTimesOnManyQueuesOnlyReceivesAppropriateLifetimeEvents() {
  405. // Given
  406. let eventMonitor = ClosureEventMonitor()
  407. let session = Session(eventMonitors: [eventMonitor])
  408. let expect = expectation(description: "request should receive appropriate lifetime events")
  409. expect.expectedFulfillmentCount = 6
  410. eventMonitor.requestDidCancelTask = { _, _ in expect.fulfill() }
  411. eventMonitor.requestDidCancel = { _ in expect.fulfill() }
  412. eventMonitor.requestDidResume = { _ in expect.fulfill() }
  413. eventMonitor.requestDidResumeTask = { _, _ 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. // When
  418. let request = session.request(URLRequest.makeHTTPBinRequest()).response { _ in expect.fulfill() }
  419. // Cancellation stops task creation, so don't cancel the request until the task has been created.
  420. eventMonitor.requestDidCreateTask = { _, _ in
  421. DispatchQueue.concurrentPerform(iterations: 100) { i in
  422. request.cancel()
  423. if i == 99 { expect.fulfill() }
  424. }
  425. }
  426. waitForExpectations(timeout: timeout, handler: nil)
  427. // Then
  428. XCTAssertEqual(request.state, .cancelled)
  429. }
  430. func testThatRequestTriggersAllAppropriateLifetimeEvents() {
  431. // Given
  432. let eventMonitor = ClosureEventMonitor()
  433. let session = Session(eventMonitors: [eventMonitor])
  434. let didReceiveChallenge = expectation(description: "didReceiveChallenge should fire")
  435. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  436. let didReceiveData = expectation(description: "didReceiveData should fire")
  437. let willCacheResponse = expectation(description: "willCacheResponse should fire")
  438. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  439. let didCreateTask = expectation(description: "didCreateTask should fire")
  440. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  441. let didComplete = expectation(description: "didComplete should fire")
  442. let didFinish = expectation(description: "didFinish should fire")
  443. let didResume = expectation(description: "didResume should fire")
  444. let didResumeTask = expectation(description: "didResumeTask should fire")
  445. let didParseResponse = expectation(description: "didParseResponse should fire")
  446. let responseHandler = expectation(description: "responseHandler should fire")
  447. var dataReceived = false
  448. eventMonitor.taskDidReceiveChallenge = { _, _, _ in didReceiveChallenge.fulfill() }
  449. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  450. eventMonitor.dataTaskDidReceiveData = { _, _, _ in
  451. guard !dataReceived else { return }
  452. // Data may be received many times, fulfill only once.
  453. dataReceived = true
  454. didReceiveData.fulfill()
  455. }
  456. eventMonitor.dataTaskWillCacheResponse = { _, _, _ in willCacheResponse.fulfill() }
  457. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  458. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  459. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  460. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  461. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  462. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  463. eventMonitor.requestDidResumeTask = { _, _ in didResumeTask.fulfill() }
  464. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  465. // When
  466. let request = session.request(URLRequest.makeHTTPBinRequest()).response { _ in
  467. responseHandler.fulfill()
  468. }
  469. waitForExpectations(timeout: timeout, handler: nil)
  470. // Then
  471. XCTAssertEqual(request.state, .finished)
  472. }
  473. func testThatCancelledRequestTriggersAllAppropriateLifetimeEvents() {
  474. // Given
  475. let queue = DispatchQueue(label: "org.alamofire.Session.TestRootQueue")
  476. let eventMonitor = ClosureEventMonitor(queue: queue)
  477. let session = Session(rootQueue: queue, startRequestsImmediately: false, eventMonitors: [eventMonitor])
  478. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  479. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  480. let didCreateTask = expectation(description: "didCreateTask should fire")
  481. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  482. let didComplete = expectation(description: "didComplete should fire")
  483. let didFinish = expectation(description: "didFinish should fire")
  484. let didResume = expectation(description: "didResume should fire")
  485. let didResumeTask = expectation(description: "didResumeTask should fire")
  486. let didParseResponse = expectation(description: "didParseResponse should fire")
  487. let didCancel = expectation(description: "didCancel should fire")
  488. let didCancelTask = expectation(description: "didCancelTask should fire")
  489. let responseHandler = expectation(description: "responseHandler should fire")
  490. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  491. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  492. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  493. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  494. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  495. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  496. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  497. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  498. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  499. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  500. // When
  501. let request = session.request(URLRequest.makeHTTPBinRequest()).response { _ in
  502. responseHandler.fulfill()
  503. }
  504. eventMonitor.requestDidResumeTask = { _, _ in
  505. request.cancel()
  506. didResumeTask.fulfill()
  507. }
  508. request.resume()
  509. waitForExpectations(timeout: timeout, handler: nil)
  510. // Then
  511. XCTAssertEqual(request.state, .cancelled)
  512. }
  513. func testThatAppendingResponseSerializerToCancelledRequestCallsCompletion() {
  514. // Given
  515. let session = Session()
  516. var response1: DataResponse<Any, AFError>?
  517. var response2: DataResponse<Any, AFError>?
  518. let expect = expectation(description: "both response serializer completions should be called")
  519. expect.expectedFulfillmentCount = 2
  520. // When
  521. let request = session.request(URLRequest.makeHTTPBinRequest())
  522. request.responseJSON { resp in
  523. response1 = resp
  524. expect.fulfill()
  525. request.responseJSON { resp in
  526. response2 = resp
  527. expect.fulfill()
  528. }
  529. }
  530. request.cancel()
  531. waitForExpectations(timeout: timeout, handler: nil)
  532. // Then
  533. XCTAssertEqual(response1?.error?.isExplicitlyCancelledError, true)
  534. XCTAssertEqual(response2?.error?.isExplicitlyCancelledError, true)
  535. }
  536. func testThatAppendingResponseSerializerToCompletedRequestInsideCompletionResumesRequest() {
  537. // Given
  538. let session = Session()
  539. var response1: DataResponse<Any, AFError>?
  540. var response2: DataResponse<Any, AFError>?
  541. var response3: DataResponse<Any, AFError>?
  542. let expect = expectation(description: "all response serializer completions should be called")
  543. expect.expectedFulfillmentCount = 3
  544. // When
  545. let request = session.request(URLRequest.makeHTTPBinRequest())
  546. request.responseJSON { resp in
  547. response1 = resp
  548. expect.fulfill()
  549. request.responseJSON { resp in
  550. response2 = resp
  551. expect.fulfill()
  552. request.responseJSON { resp in
  553. response3 = resp
  554. expect.fulfill()
  555. }
  556. }
  557. }
  558. waitForExpectations(timeout: timeout, handler: nil)
  559. // Then
  560. XCTAssertNotNil(response1?.value)
  561. XCTAssertNotNil(response2?.value)
  562. XCTAssertNotNil(response3?.value)
  563. }
  564. func testThatAppendingResponseSerializerToCompletedRequestOutsideCompletionResumesRequest() {
  565. // Given
  566. let session = Session()
  567. let request = session.request(URLRequest.makeHTTPBinRequest())
  568. var response1: DataResponse<Any, AFError>?
  569. var response2: DataResponse<Any, AFError>?
  570. var response3: DataResponse<Any, AFError>?
  571. // When
  572. let expect1 = expectation(description: "response serializer 1 completion should be called")
  573. request.responseJSON { response1 = $0; expect1.fulfill() }
  574. waitForExpectations(timeout: timeout, handler: nil)
  575. let expect2 = expectation(description: "response serializer 2 completion should be called")
  576. request.responseJSON { response2 = $0; expect2.fulfill() }
  577. waitForExpectations(timeout: timeout, handler: nil)
  578. let expect3 = expectation(description: "response serializer 3 completion should be called")
  579. request.responseJSON { response3 = $0; expect3.fulfill() }
  580. waitForExpectations(timeout: timeout, handler: nil)
  581. // Then
  582. XCTAssertNotNil(response1?.value)
  583. XCTAssertNotNil(response2?.value)
  584. XCTAssertNotNil(response3?.value)
  585. }
  586. }
  587. // MARK: -
  588. class RequestDescriptionTestCase: BaseTestCase {
  589. func testRequestDescription() {
  590. // Given
  591. let urlString = "https://httpbin.org/get"
  592. let manager = Session(startRequestsImmediately: false)
  593. let request = manager.request(urlString)
  594. let expectation = self.expectation(description: "Request description should update: \(urlString)")
  595. var response: HTTPURLResponse?
  596. // When
  597. request.response { resp in
  598. response = resp.response
  599. expectation.fulfill()
  600. }.resume()
  601. waitForExpectations(timeout: timeout, handler: nil)
  602. // Then
  603. XCTAssertEqual(request.description, "GET https://httpbin.org/get (\(response?.statusCode ?? -1))")
  604. }
  605. }
  606. // MARK: -
  607. final class RequestCURLDescriptionTestCase: BaseTestCase {
  608. // MARK: Properties
  609. let manager: Session = {
  610. let manager = Session()
  611. return manager
  612. }()
  613. let managerWithAcceptLanguageHeader: Session = {
  614. var headers = HTTPHeaders.default
  615. headers["Accept-Language"] = "en-US"
  616. let configuration = URLSessionConfiguration.af.default
  617. configuration.headers = headers
  618. let manager = Session(configuration: configuration)
  619. return manager
  620. }()
  621. let managerWithContentTypeHeader: Session = {
  622. var headers = HTTPHeaders.default
  623. headers["Content-Type"] = "application/json"
  624. let configuration = URLSessionConfiguration.af.default
  625. configuration.headers = headers
  626. let manager = Session(configuration: configuration)
  627. return manager
  628. }()
  629. func managerWithCookie(_ cookie: HTTPCookie) -> Session {
  630. let configuration = URLSessionConfiguration.af.default
  631. configuration.httpCookieStorage?.setCookie(cookie)
  632. return Session(configuration: configuration)
  633. }
  634. let managerDisallowingCookies: Session = {
  635. let configuration = URLSessionConfiguration.af.default
  636. configuration.httpShouldSetCookies = false
  637. let manager = Session(configuration: configuration)
  638. return manager
  639. }()
  640. // MARK: Tests
  641. func testGETRequestCURLDescription() {
  642. // Given
  643. let urlString = "https://httpbin.org/get"
  644. let expectation = self.expectation(description: "request should complete")
  645. var components: [String]?
  646. // When
  647. manager.request(urlString).cURLDescription {
  648. components = self.cURLCommandComponents(from: $0)
  649. expectation.fulfill()
  650. }
  651. waitForExpectations(timeout: timeout, handler: nil)
  652. // Then
  653. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  654. XCTAssertTrue(components?.contains("-X") == true)
  655. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  656. }
  657. func testGETRequestCURLDescriptionSynchronous() {
  658. // Given
  659. let urlString = "https://httpbin.org/get"
  660. let expectation = self.expectation(description: "request should complete")
  661. var components: [String]?
  662. var syncComponents: [String]?
  663. // When
  664. let request = manager.request(urlString)
  665. request.cURLDescription {
  666. components = self.cURLCommandComponents(from: $0)
  667. syncComponents = self.cURLCommandComponents(from: request.cURLDescription())
  668. expectation.fulfill()
  669. }
  670. waitForExpectations(timeout: timeout, handler: nil)
  671. // Then
  672. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  673. XCTAssertTrue(components?.contains("-X") == true)
  674. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  675. XCTAssertEqual(components?.sorted(), syncComponents?.sorted())
  676. }
  677. func testGETRequestCURLDescriptionCanBeRequestedManyTimes() {
  678. // Given
  679. let urlString = "https://httpbin.org/get"
  680. let expectation = self.expectation(description: "request should complete")
  681. var components: [String]?
  682. var secondComponents: [String]?
  683. // When
  684. let request = manager.request(urlString)
  685. request.cURLDescription {
  686. components = self.cURLCommandComponents(from: $0)
  687. request.cURLDescription {
  688. secondComponents = self.cURLCommandComponents(from: $0)
  689. expectation.fulfill()
  690. }
  691. }
  692. // Trigger the overwrite behavior.
  693. request.cURLDescription {
  694. components = self.cURLCommandComponents(from: $0)
  695. request.cURLDescription {
  696. secondComponents = self.cURLCommandComponents(from: $0)
  697. expectation.fulfill()
  698. }
  699. }
  700. waitForExpectations(timeout: timeout, handler: nil)
  701. // Then
  702. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  703. XCTAssertTrue(components?.contains("-X") == true)
  704. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  705. XCTAssertEqual(components?.sorted(), secondComponents?.sorted())
  706. }
  707. func testGETRequestWithCustomHeaderCURLDescription() {
  708. // Given
  709. let urlString = "https://httpbin.org/get"
  710. let expectation = self.expectation(description: "request should complete")
  711. var cURLDescription: String?
  712. // When
  713. let headers: HTTPHeaders = ["X-Custom-Header": "{\"key\": \"value\"}"]
  714. manager.request(urlString, headers: headers).cURLDescription {
  715. cURLDescription = $0
  716. expectation.fulfill()
  717. }
  718. waitForExpectations(timeout: timeout, handler: nil)
  719. // Then
  720. XCTAssertNotNil(cURLDescription?.range(of: "-H \"X-Custom-Header: {\\\"key\\\": \\\"value\\\"}\""))
  721. }
  722. func testGETRequestWithDuplicateHeadersDebugDescription() {
  723. // Given
  724. let urlString = "https://httpbin.org/get"
  725. let expectation = self.expectation(description: "request should complete")
  726. var cURLDescription: String?
  727. var components: [String]?
  728. // When
  729. let headers: HTTPHeaders = ["Accept-Language": "en-GB"]
  730. managerWithAcceptLanguageHeader.request(urlString, headers: headers).cURLDescription {
  731. components = self.cURLCommandComponents(from: $0)
  732. cURLDescription = $0
  733. expectation.fulfill()
  734. }
  735. waitForExpectations(timeout: timeout, handler: nil)
  736. // Then
  737. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  738. XCTAssertTrue(components?.contains("-X") == true)
  739. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  740. let acceptLanguageCount = components?.filter { $0.contains("Accept-Language") }.count
  741. XCTAssertEqual(acceptLanguageCount, 1, "command should contain a single Accept-Language header")
  742. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Accept-Language: en-GB\""))
  743. }
  744. func testPOSTRequestCURLDescription() {
  745. // Given
  746. let urlString = "https://httpbin.org/post"
  747. let expectation = self.expectation(description: "request should complete")
  748. var components: [String]?
  749. // When
  750. manager.request(urlString, method: .post).cURLDescription {
  751. components = self.cURLCommandComponents(from: $0)
  752. expectation.fulfill()
  753. }
  754. waitForExpectations(timeout: timeout, handler: nil)
  755. // Then
  756. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  757. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  758. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  759. }
  760. func testPOSTRequestWithJSONParametersCURLDescription() {
  761. // Given
  762. let urlString = "https://httpbin.org/post"
  763. let expectation = self.expectation(description: "request should complete")
  764. var cURLDescription: String?
  765. var components: [String]?
  766. let parameters = ["foo": "bar",
  767. "fo\"o": "b\"ar",
  768. "f'oo": "ba'r"]
  769. // When
  770. manager.request(urlString, method: .post, parameters: parameters, encoding: JSONEncoding.default).cURLDescription {
  771. components = self.cURLCommandComponents(from: $0)
  772. cURLDescription = $0
  773. expectation.fulfill()
  774. }
  775. waitForExpectations(timeout: timeout, handler: nil)
  776. // Then
  777. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  778. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  779. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: application/json\""))
  780. XCTAssertNotNil(cURLDescription?.range(of: "-d \"{"))
  781. XCTAssertNotNil(cURLDescription?.range(of: "\\\"f'oo\\\":\\\"ba'r\\\""))
  782. XCTAssertNotNil(cURLDescription?.range(of: "\\\"fo\\\\\\\"o\\\":\\\"b\\\\\\\"ar\\\""))
  783. XCTAssertNotNil(cURLDescription?.range(of: "\\\"foo\\\":\\\"bar\\"))
  784. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  785. }
  786. func testPOSTRequestWithCookieCURLDescription() {
  787. // Given
  788. let urlString = "https://httpbin.org/post"
  789. let properties = [HTTPCookiePropertyKey.domain: "httpbin.org",
  790. HTTPCookiePropertyKey.path: "/post",
  791. HTTPCookiePropertyKey.name: "foo",
  792. HTTPCookiePropertyKey.value: "bar"]
  793. let cookie = HTTPCookie(properties: properties)!
  794. let cookieManager = managerWithCookie(cookie)
  795. let expectation = self.expectation(description: "request should complete")
  796. var components: [String]?
  797. // When
  798. cookieManager.request(urlString, method: .post).cURLDescription {
  799. components = self.cURLCommandComponents(from: $0)
  800. expectation.fulfill()
  801. }
  802. waitForExpectations(timeout: timeout, handler: nil)
  803. // Then
  804. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  805. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  806. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  807. XCTAssertEqual(components?[5..<6], ["-b"])
  808. }
  809. func testPOSTRequestWithCookiesDisabledCURLDescriptionHasNoCookies() {
  810. // Given
  811. let urlString = "https://httpbin.org/post"
  812. let properties = [HTTPCookiePropertyKey.domain: "httpbin.org",
  813. HTTPCookiePropertyKey.path: "/post",
  814. HTTPCookiePropertyKey.name: "foo",
  815. HTTPCookiePropertyKey.value: "bar"]
  816. let cookie = HTTPCookie(properties: properties)!
  817. managerDisallowingCookies.session.configuration.httpCookieStorage?.setCookie(cookie)
  818. let expectation = self.expectation(description: "request should complete")
  819. var components: [String]?
  820. // When
  821. managerDisallowingCookies.request(urlString, method: .post).cURLDescription {
  822. components = self.cURLCommandComponents(from: $0)
  823. expectation.fulfill()
  824. }
  825. waitForExpectations(timeout: timeout, handler: nil)
  826. // Then
  827. let cookieComponents = components?.filter { $0 == "-b" }
  828. XCTAssertTrue(cookieComponents?.isEmpty == true)
  829. }
  830. func testMultipartFormDataRequestWithDuplicateHeadersCURLDescriptionHasOneContentTypeHeader() {
  831. // Given
  832. let urlString = "https://httpbin.org/post"
  833. let japaneseData = Data("日本語".utf8)
  834. let expectation = self.expectation(description: "multipart form data encoding should succeed")
  835. var cURLDescription: String?
  836. var components: [String]?
  837. // When
  838. managerWithContentTypeHeader.upload(multipartFormData: { data in
  839. data.append(japaneseData, withName: "japanese")
  840. }, to: urlString).cURLDescription {
  841. components = self.cURLCommandComponents(from: $0)
  842. cURLDescription = $0
  843. expectation.fulfill()
  844. }
  845. waitForExpectations(timeout: timeout, handler: nil)
  846. // Then
  847. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  848. XCTAssertTrue(components?.contains("-X") == true)
  849. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  850. let contentTypeCount = components?.filter { $0.contains("Content-Type") }.count
  851. XCTAssertEqual(contentTypeCount, 1, "command should contain a single Content-Type header")
  852. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: multipart/form-data;"))
  853. }
  854. func testThatRequestWithInvalidURLDebugDescription() {
  855. // Given
  856. let urlString = "invalid_url"
  857. let expectation = self.expectation(description: "request should complete")
  858. var cURLDescription: String?
  859. // When
  860. manager.request(urlString).cURLDescription {
  861. cURLDescription = $0
  862. expectation.fulfill()
  863. }
  864. waitForExpectations(timeout: timeout, handler: nil)
  865. // Then
  866. XCTAssertNotNil(cURLDescription, "debugDescription should not crash")
  867. }
  868. // MARK: Test Helper Methods
  869. private func cURLCommandComponents(from cURLString: String) -> [String] {
  870. return cURLString.components(separatedBy: .whitespacesAndNewlines)
  871. .filter { $0 != "" && $0 != "\\" }
  872. }
  873. }