RequestTests.swift 42 KB

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