2
0

RequestTests.swift 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  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 * 1024 * 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 eventMonitor = ClosureEventMonitor()
  476. let session = Session(startRequestsImmediately: false, eventMonitors: [eventMonitor])
  477. let taskDidFinishCollecting = expectation(description: "taskDidFinishCollecting should fire")
  478. let didCreateURLRequest = expectation(description: "didCreateInitialURLRequest should fire")
  479. let didCreateTask = expectation(description: "didCreateTask should fire")
  480. let didGatherMetrics = expectation(description: "didGatherMetrics should fire")
  481. let didComplete = expectation(description: "didComplete should fire")
  482. let didFinish = expectation(description: "didFinish should fire")
  483. let didResume = expectation(description: "didResume should fire")
  484. let didResumeTask = expectation(description: "didResumeTask should fire")
  485. let didParseResponse = expectation(description: "didParseResponse should fire")
  486. let didCancel = expectation(description: "didCancel should fire")
  487. let didCancelTask = expectation(description: "didCancelTask should fire")
  488. let responseHandler = expectation(description: "responseHandler should fire")
  489. eventMonitor.taskDidFinishCollectingMetrics = { _, _, _ in taskDidFinishCollecting.fulfill() }
  490. eventMonitor.requestDidCreateInitialURLRequest = { _, _ in didCreateURLRequest.fulfill() }
  491. eventMonitor.requestDidCreateTask = { _, _ in didCreateTask.fulfill() }
  492. eventMonitor.requestDidGatherMetrics = { _, _ in didGatherMetrics.fulfill() }
  493. eventMonitor.requestDidCompleteTaskWithError = { _, _, _ in didComplete.fulfill() }
  494. eventMonitor.requestDidFinish = { _ in didFinish.fulfill() }
  495. eventMonitor.requestDidResume = { _ in didResume.fulfill() }
  496. eventMonitor.requestDidParseResponse = { _, _ in didParseResponse.fulfill() }
  497. eventMonitor.requestDidCancel = { _ in didCancel.fulfill() }
  498. eventMonitor.requestDidCancelTask = { _, _ in didCancelTask.fulfill() }
  499. // When
  500. let request = session.request(URLRequest.makeHTTPBinRequest()).response { _ in
  501. responseHandler.fulfill()
  502. }
  503. eventMonitor.requestDidResumeTask = { _, _ in
  504. request.cancel()
  505. didResumeTask.fulfill()
  506. }
  507. request.resume()
  508. waitForExpectations(timeout: timeout, handler: nil)
  509. // Then
  510. XCTAssertEqual(request.state, .cancelled)
  511. }
  512. func testThatAppendingResponseSerializerToCancelledRequestCallsCompletion() {
  513. // Given
  514. let session = Session()
  515. var response1: DataResponse<Any, AFError>?
  516. var response2: DataResponse<Any, AFError>?
  517. let expect = expectation(description: "both response serializer completions should be called")
  518. expect.expectedFulfillmentCount = 2
  519. // When
  520. let request = session.request(URLRequest.makeHTTPBinRequest())
  521. request.responseJSON { resp in
  522. response1 = resp
  523. expect.fulfill()
  524. request.responseJSON { resp in
  525. response2 = resp
  526. expect.fulfill()
  527. }
  528. }
  529. request.cancel()
  530. waitForExpectations(timeout: timeout, handler: nil)
  531. // Then
  532. XCTAssertEqual(response1?.error?.isExplicitlyCancelledError, true)
  533. XCTAssertEqual(response2?.error?.isExplicitlyCancelledError, true)
  534. }
  535. func testThatAppendingResponseSerializerToCompletedRequestInsideCompletionResumesRequest() {
  536. // Given
  537. let session = Session()
  538. var response1: DataResponse<Any, AFError>?
  539. var response2: DataResponse<Any, AFError>?
  540. var response3: DataResponse<Any, AFError>?
  541. let expect = expectation(description: "all response serializer completions should be called")
  542. expect.expectedFulfillmentCount = 3
  543. // When
  544. let request = session.request(URLRequest.makeHTTPBinRequest())
  545. request.responseJSON { resp in
  546. response1 = resp
  547. expect.fulfill()
  548. request.responseJSON { resp in
  549. response2 = resp
  550. expect.fulfill()
  551. request.responseJSON { resp in
  552. response3 = resp
  553. expect.fulfill()
  554. }
  555. }
  556. }
  557. waitForExpectations(timeout: timeout, handler: nil)
  558. // Then
  559. XCTAssertNotNil(response1?.value)
  560. XCTAssertNotNil(response2?.value)
  561. XCTAssertNotNil(response3?.value)
  562. }
  563. func testThatAppendingResponseSerializerToCompletedRequestOutsideCompletionResumesRequest() {
  564. // Given
  565. let session = Session()
  566. let request = session.request(URLRequest.makeHTTPBinRequest())
  567. var response1: DataResponse<Any, AFError>?
  568. var response2: DataResponse<Any, AFError>?
  569. var response3: DataResponse<Any, AFError>?
  570. // When
  571. let expect1 = expectation(description: "response serializer 1 completion should be called")
  572. request.responseJSON { response1 = $0; expect1.fulfill() }
  573. waitForExpectations(timeout: timeout, handler: nil)
  574. let expect2 = expectation(description: "response serializer 2 completion should be called")
  575. request.responseJSON { response2 = $0; expect2.fulfill() }
  576. waitForExpectations(timeout: timeout, handler: nil)
  577. let expect3 = expectation(description: "response serializer 3 completion should be called")
  578. request.responseJSON { response3 = $0; expect3.fulfill() }
  579. waitForExpectations(timeout: timeout, handler: nil)
  580. // Then
  581. XCTAssertNotNil(response1?.value)
  582. XCTAssertNotNil(response2?.value)
  583. XCTAssertNotNil(response3?.value)
  584. }
  585. }
  586. // MARK: -
  587. class RequestDescriptionTestCase: BaseTestCase {
  588. func testRequestDescription() {
  589. // Given
  590. let urlString = "https://httpbin.org/get"
  591. let manager = Session(startRequestsImmediately: false)
  592. let request = manager.request(urlString)
  593. let expectation = self.expectation(description: "Request description should update: \(urlString)")
  594. var response: HTTPURLResponse?
  595. // When
  596. request.response { resp in
  597. response = resp.response
  598. expectation.fulfill()
  599. }.resume()
  600. waitForExpectations(timeout: timeout, handler: nil)
  601. // Then
  602. XCTAssertEqual(request.description, "GET https://httpbin.org/get (\(response?.statusCode ?? -1))")
  603. }
  604. }
  605. // MARK: -
  606. final class RequestCURLDescriptionTestCase: BaseTestCase {
  607. // MARK: Properties
  608. let manager: Session = {
  609. let manager = Session()
  610. return manager
  611. }()
  612. let managerWithAcceptLanguageHeader: Session = {
  613. var headers = HTTPHeaders.default
  614. headers["Accept-Language"] = "en-US"
  615. let configuration = URLSessionConfiguration.af.default
  616. configuration.headers = headers
  617. let manager = Session(configuration: configuration)
  618. return manager
  619. }()
  620. let managerWithContentTypeHeader: Session = {
  621. var headers = HTTPHeaders.default
  622. headers["Content-Type"] = "application/json"
  623. let configuration = URLSessionConfiguration.af.default
  624. configuration.headers = headers
  625. let manager = Session(configuration: configuration)
  626. return manager
  627. }()
  628. func managerWithCookie(_ cookie: HTTPCookie) -> Session {
  629. let configuration = URLSessionConfiguration.af.default
  630. configuration.httpCookieStorage?.setCookie(cookie)
  631. return Session(configuration: configuration)
  632. }
  633. let managerDisallowingCookies: Session = {
  634. let configuration = URLSessionConfiguration.af.default
  635. configuration.httpShouldSetCookies = false
  636. let manager = Session(configuration: configuration)
  637. return manager
  638. }()
  639. // MARK: Tests
  640. func testGETRequestCURLDescription() {
  641. // Given
  642. let urlString = "https://httpbin.org/get"
  643. let expectation = self.expectation(description: "request should complete")
  644. var components: [String]?
  645. // When
  646. manager.request(urlString).cURLDescription {
  647. components = self.cURLCommandComponents(from: $0)
  648. expectation.fulfill()
  649. }
  650. waitForExpectations(timeout: timeout, handler: nil)
  651. // Then
  652. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  653. XCTAssertTrue(components?.contains("-X") == true)
  654. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  655. }
  656. func testGETRequestCURLDescriptionSynchronous() {
  657. // Given
  658. let urlString = "https://httpbin.org/get"
  659. let expectation = self.expectation(description: "request should complete")
  660. var components: [String]?
  661. var syncComponents: [String]?
  662. // When
  663. let request = manager.request(urlString)
  664. request.cURLDescription {
  665. components = self.cURLCommandComponents(from: $0)
  666. syncComponents = self.cURLCommandComponents(from: request.cURLDescription())
  667. expectation.fulfill()
  668. }
  669. waitForExpectations(timeout: timeout, handler: nil)
  670. // Then
  671. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  672. XCTAssertTrue(components?.contains("-X") == true)
  673. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  674. XCTAssertEqual(components?.sorted(), syncComponents?.sorted())
  675. }
  676. func testGETRequestCURLDescriptionCanBeRequestedManyTimes() {
  677. // Given
  678. let urlString = "https://httpbin.org/get"
  679. let expectation = self.expectation(description: "request should complete")
  680. var components: [String]?
  681. var secondComponents: [String]?
  682. // When
  683. let request = manager.request(urlString)
  684. request.cURLDescription {
  685. components = self.cURLCommandComponents(from: $0)
  686. request.cURLDescription {
  687. secondComponents = self.cURLCommandComponents(from: $0)
  688. expectation.fulfill()
  689. }
  690. }
  691. // Trigger the overwrite behavior.
  692. request.cURLDescription {
  693. components = self.cURLCommandComponents(from: $0)
  694. request.cURLDescription {
  695. secondComponents = self.cURLCommandComponents(from: $0)
  696. expectation.fulfill()
  697. }
  698. }
  699. waitForExpectations(timeout: timeout, handler: nil)
  700. // Then
  701. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  702. XCTAssertTrue(components?.contains("-X") == true)
  703. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  704. XCTAssertEqual(components?.sorted(), secondComponents?.sorted())
  705. }
  706. func testGETRequestWithCustomHeaderCURLDescription() {
  707. // Given
  708. let urlString = "https://httpbin.org/get"
  709. let expectation = self.expectation(description: "request should complete")
  710. var cURLDescription: String?
  711. // When
  712. let headers: HTTPHeaders = ["X-Custom-Header": "{\"key\": \"value\"}"]
  713. manager.request(urlString, headers: headers).cURLDescription {
  714. cURLDescription = $0
  715. expectation.fulfill()
  716. }
  717. waitForExpectations(timeout: timeout, handler: nil)
  718. // Then
  719. XCTAssertNotNil(cURLDescription?.range(of: "-H \"X-Custom-Header: {\\\"key\\\": \\\"value\\\"}\""))
  720. }
  721. func testGETRequestWithDuplicateHeadersDebugDescription() {
  722. // Given
  723. let urlString = "https://httpbin.org/get"
  724. let expectation = self.expectation(description: "request should complete")
  725. var cURLDescription: String?
  726. var components: [String]?
  727. // When
  728. let headers: HTTPHeaders = ["Accept-Language": "en-GB"]
  729. managerWithAcceptLanguageHeader.request(urlString, headers: headers).cURLDescription {
  730. components = self.cURLCommandComponents(from: $0)
  731. cURLDescription = $0
  732. expectation.fulfill()
  733. }
  734. waitForExpectations(timeout: timeout, handler: nil)
  735. // Then
  736. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  737. XCTAssertTrue(components?.contains("-X") == true)
  738. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  739. let acceptLanguageCount = components?.filter { $0.contains("Accept-Language") }.count
  740. XCTAssertEqual(acceptLanguageCount, 1, "command should contain a single Accept-Language header")
  741. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Accept-Language: en-GB\""))
  742. }
  743. func testPOSTRequestCURLDescription() {
  744. // Given
  745. let urlString = "https://httpbin.org/post"
  746. let expectation = self.expectation(description: "request should complete")
  747. var components: [String]?
  748. // When
  749. manager.request(urlString, method: .post).cURLDescription {
  750. components = self.cURLCommandComponents(from: $0)
  751. expectation.fulfill()
  752. }
  753. waitForExpectations(timeout: timeout, handler: nil)
  754. // Then
  755. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  756. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  757. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  758. }
  759. func testPOSTRequestWithJSONParametersCURLDescription() {
  760. // Given
  761. let urlString = "https://httpbin.org/post"
  762. let expectation = self.expectation(description: "request should complete")
  763. var cURLDescription: String?
  764. var components: [String]?
  765. let parameters = ["foo": "bar",
  766. "fo\"o": "b\"ar",
  767. "f'oo": "ba'r"]
  768. // When
  769. manager.request(urlString, method: .post, parameters: parameters, encoding: JSONEncoding.default).cURLDescription {
  770. components = self.cURLCommandComponents(from: $0)
  771. cURLDescription = $0
  772. expectation.fulfill()
  773. }
  774. waitForExpectations(timeout: timeout, handler: nil)
  775. // Then
  776. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  777. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  778. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: application/json\""))
  779. XCTAssertNotNil(cURLDescription?.range(of: "-d \"{"))
  780. XCTAssertNotNil(cURLDescription?.range(of: "\\\"f'oo\\\":\\\"ba'r\\\""))
  781. XCTAssertNotNil(cURLDescription?.range(of: "\\\"fo\\\\\\\"o\\\":\\\"b\\\\\\\"ar\\\""))
  782. XCTAssertNotNil(cURLDescription?.range(of: "\\\"foo\\\":\\\"bar\\"))
  783. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  784. }
  785. func testPOSTRequestWithCookieCURLDescription() {
  786. // Given
  787. let urlString = "https://httpbin.org/post"
  788. let properties = [HTTPCookiePropertyKey.domain: "httpbin.org",
  789. HTTPCookiePropertyKey.path: "/post",
  790. HTTPCookiePropertyKey.name: "foo",
  791. HTTPCookiePropertyKey.value: "bar"]
  792. let cookie = HTTPCookie(properties: properties)!
  793. let cookieManager = managerWithCookie(cookie)
  794. let expectation = self.expectation(description: "request should complete")
  795. var components: [String]?
  796. // When
  797. cookieManager.request(urlString, method: .post).cURLDescription {
  798. components = self.cURLCommandComponents(from: $0)
  799. expectation.fulfill()
  800. }
  801. waitForExpectations(timeout: timeout, handler: nil)
  802. // Then
  803. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  804. XCTAssertEqual(components?[3..<5], ["-X", "POST"])
  805. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  806. XCTAssertEqual(components?[5..<6], ["-b"])
  807. }
  808. func testPOSTRequestWithCookiesDisabledCURLDescriptionHasNoCookies() {
  809. // Given
  810. let urlString = "https://httpbin.org/post"
  811. let properties = [HTTPCookiePropertyKey.domain: "httpbin.org",
  812. HTTPCookiePropertyKey.path: "/post",
  813. HTTPCookiePropertyKey.name: "foo",
  814. HTTPCookiePropertyKey.value: "bar"]
  815. let cookie = HTTPCookie(properties: properties)!
  816. managerDisallowingCookies.session.configuration.httpCookieStorage?.setCookie(cookie)
  817. let expectation = self.expectation(description: "request should complete")
  818. var components: [String]?
  819. // When
  820. managerDisallowingCookies.request(urlString, method: .post).cURLDescription {
  821. components = self.cURLCommandComponents(from: $0)
  822. expectation.fulfill()
  823. }
  824. waitForExpectations(timeout: timeout, handler: nil)
  825. // Then
  826. let cookieComponents = components?.filter { $0 == "-b" }
  827. XCTAssertTrue(cookieComponents?.isEmpty == true)
  828. }
  829. func testMultipartFormDataRequestWithDuplicateHeadersCURLDescriptionHasOneContentTypeHeader() {
  830. // Given
  831. let urlString = "https://httpbin.org/post"
  832. let japaneseData = Data("日本語".utf8)
  833. let expectation = self.expectation(description: "multipart form data encoding should succeed")
  834. var cURLDescription: String?
  835. var components: [String]?
  836. // When
  837. managerWithContentTypeHeader.upload(multipartFormData: { data in
  838. data.append(japaneseData, withName: "japanese")
  839. }, to: urlString).cURLDescription {
  840. components = self.cURLCommandComponents(from: $0)
  841. cURLDescription = $0
  842. expectation.fulfill()
  843. }
  844. waitForExpectations(timeout: timeout, handler: nil)
  845. // Then
  846. XCTAssertEqual(components?[0..<3], ["$", "curl", "-v"])
  847. XCTAssertTrue(components?.contains("-X") == true)
  848. XCTAssertEqual(components?.last, "\"\(urlString)\"")
  849. let contentTypeCount = components?.filter { $0.contains("Content-Type") }.count
  850. XCTAssertEqual(contentTypeCount, 1, "command should contain a single Content-Type header")
  851. XCTAssertNotNil(cURLDescription?.range(of: "-H \"Content-Type: multipart/form-data;"))
  852. }
  853. func testThatRequestWithInvalidURLDebugDescription() {
  854. // Given
  855. let urlString = "invalid_url"
  856. let expectation = self.expectation(description: "request should complete")
  857. var cURLDescription: String?
  858. // When
  859. manager.request(urlString).cURLDescription {
  860. cURLDescription = $0
  861. expectation.fulfill()
  862. }
  863. waitForExpectations(timeout: timeout, handler: nil)
  864. // Then
  865. XCTAssertNotNil(cURLDescription, "debugDescription should not crash")
  866. }
  867. // MARK: Test Helper Methods
  868. private func cURLCommandComponents(from cURLString: String) -> [String] {
  869. return cURLString.components(separatedBy: .whitespacesAndNewlines)
  870. .filter { $0 != "" && $0 != "\\" }
  871. }
  872. }