SessionManagerTests.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //
  2. // SessionManagerTests.swift
  3. //
  4. // Copyright (c) 2014-2016 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. @testable import Alamofire
  25. import Foundation
  26. import XCTest
  27. class SessionManagerTestCase: BaseTestCase {
  28. // MARK: Helper Types
  29. private class HTTPMethodAdapter: RequestAdapter {
  30. let method: HTTPMethod
  31. init(method: HTTPMethod) {
  32. self.method = method
  33. }
  34. func adapt(_ urlRequest: URLRequest) -> URLRequest {
  35. var urlRequest = urlRequest
  36. urlRequest.httpMethod = method.rawValue
  37. return urlRequest
  38. }
  39. }
  40. // MARK: Tests - Initialization
  41. func testInitializerWithDefaultArguments() {
  42. // Given, When
  43. let manager = SessionManager()
  44. // Then
  45. XCTAssertNotNil(manager.session.delegate, "session delegate should not be nil")
  46. XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
  47. XCTAssertNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should be nil")
  48. }
  49. func testInitializerWithSpecifiedArguments() {
  50. // Given
  51. let configuration = URLSessionConfiguration.default
  52. let delegate = SessionDelegate()
  53. let serverTrustPolicyManager = ServerTrustPolicyManager(policies: [:])
  54. // When
  55. let manager = SessionManager(
  56. configuration: configuration,
  57. delegate: delegate,
  58. serverTrustPolicyManager: serverTrustPolicyManager
  59. )
  60. // Then
  61. XCTAssertNotNil(manager.session.delegate, "session delegate should not be nil")
  62. XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
  63. XCTAssertNotNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should not be nil")
  64. }
  65. func testThatFailableInitializerSucceedsWithDefaultArguments() {
  66. // Given
  67. let delegate = SessionDelegate()
  68. let session: URLSession = {
  69. let configuration = URLSessionConfiguration.default
  70. return URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
  71. }()
  72. // When
  73. let manager = SessionManager(session: session, delegate: delegate)
  74. // Then
  75. if let manager = manager {
  76. XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
  77. XCTAssertNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should be nil")
  78. } else {
  79. XCTFail("manager should not be nil")
  80. }
  81. }
  82. func testThatFailableInitializerSucceedsWithSpecifiedArguments() {
  83. // Given
  84. let delegate = SessionDelegate()
  85. let session: URLSession = {
  86. let configuration = URLSessionConfiguration.default
  87. return URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
  88. }()
  89. let serverTrustPolicyManager = ServerTrustPolicyManager(policies: [:])
  90. // When
  91. let manager = SessionManager(session: session, delegate: delegate, serverTrustPolicyManager: serverTrustPolicyManager)
  92. // Then
  93. if let manager = manager {
  94. XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
  95. XCTAssertNotNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should not be nil")
  96. } else {
  97. XCTFail("manager should not be nil")
  98. }
  99. }
  100. func testThatFailableInitializerFailsWithWhenDelegateDoesNotEqualSessionDelegate() {
  101. // Given
  102. let delegate = SessionDelegate()
  103. let session: URLSession = {
  104. let configuration = URLSessionConfiguration.default
  105. return URLSession(configuration: configuration, delegate: SessionDelegate(), delegateQueue: nil)
  106. }()
  107. // When
  108. let manager = SessionManager(session: session, delegate: delegate)
  109. // Then
  110. XCTAssertNil(manager, "manager should be nil")
  111. }
  112. func testThatFailableInitializerFailsWhenSessionDelegateIsNil() {
  113. // Given
  114. let delegate = SessionDelegate()
  115. let session: URLSession = {
  116. let configuration = URLSessionConfiguration.default
  117. return URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
  118. }()
  119. // When
  120. let manager = SessionManager(session: session, delegate: delegate)
  121. // Then
  122. XCTAssertNil(manager, "manager should be nil")
  123. }
  124. // MARK: Tests - Start Requests Immediately
  125. func testSetStartRequestsImmediatelyToFalseAndResumeRequest() {
  126. // Given
  127. let manager = SessionManager()
  128. manager.startRequestsImmediately = false
  129. let url = URL(string: "https://httpbin.org/get")!
  130. let urlRequest = URLRequest(url: url)
  131. let expectation = self.expectation(description: "\(url)")
  132. var response: HTTPURLResponse?
  133. // When
  134. manager.request(urlRequest)
  135. .response { _, responseResponse, _, _ in
  136. response = responseResponse
  137. expectation.fulfill()
  138. }
  139. .resume()
  140. waitForExpectations(timeout: timeout, handler: nil)
  141. // Then
  142. XCTAssertNotNil(response, "response should not be nil")
  143. XCTAssertTrue(response?.statusCode == 200, "response status code should be 200")
  144. }
  145. // MARK: Tests - Deinitialization
  146. func testReleasingManagerWithPendingRequestDeinitializesSuccessfully() {
  147. // Given
  148. var manager: SessionManager? = SessionManager()
  149. manager?.startRequestsImmediately = false
  150. let url = URL(string: "https://httpbin.org/get")!
  151. let urlRequest = URLRequest(url: url)
  152. // When
  153. let request = manager?.request(urlRequest)
  154. manager = nil
  155. // Then
  156. XCTAssertTrue(request?.task.state == .suspended, "request task state should be '.Suspended'")
  157. XCTAssertNil(manager, "manager should be nil")
  158. }
  159. func testReleasingManagerWithPendingCanceledRequestDeinitializesSuccessfully() {
  160. // Given
  161. var manager: SessionManager? = SessionManager()
  162. manager!.startRequestsImmediately = false
  163. let url = URL(string: "https://httpbin.org/get")!
  164. let urlRequest = URLRequest(url: url)
  165. // When
  166. let request = manager!.request(urlRequest)
  167. request.cancel()
  168. manager = nil
  169. // Then
  170. let state = request.task.state
  171. XCTAssertTrue(state == .canceling || state == .completed, "state should be .Canceling or .Completed")
  172. XCTAssertNil(manager, "manager should be nil")
  173. }
  174. // MARK: Tests - Request Adapter
  175. func testThatSessionManagerCallsRequestAdapterWhenCreatingDataRequest() {
  176. // Given
  177. let adapter = HTTPMethodAdapter(method: .post)
  178. let sessionManager = SessionManager()
  179. sessionManager.adapter = adapter
  180. sessionManager.startRequestsImmediately = false
  181. // When
  182. let request = sessionManager.request("https://httpbin.org/get", withMethod: .get)
  183. // Then
  184. XCTAssertEqual(request.task.originalRequest?.httpMethod, adapter.method.rawValue)
  185. }
  186. func testThatSessionManagerCallsRequestAdapterWhenCreatingDownloadRequest() {
  187. // Given
  188. let adapter = HTTPMethodAdapter(method: .post)
  189. let sessionManager = SessionManager()
  190. sessionManager.adapter = adapter
  191. sessionManager.startRequestsImmediately = false
  192. // When
  193. let destination = Request.suggestedDownloadDestination()
  194. let request = sessionManager.download("https://httpbin.org/get", to: destination, withMethod: .get)
  195. // Then
  196. XCTAssertEqual(request.task.originalRequest?.httpMethod, adapter.method.rawValue)
  197. }
  198. func testThatSessionManagerCallsRequestAdapterWhenCreatingUploadRequestWithData() {
  199. // Given
  200. let adapter = HTTPMethodAdapter(method: .get)
  201. let sessionManager = SessionManager()
  202. sessionManager.adapter = adapter
  203. sessionManager.startRequestsImmediately = false
  204. // When
  205. let request = sessionManager.upload("data".data(using: .utf8)!, to: "https://httpbin.org/post", withMethod: .post)
  206. // Then
  207. XCTAssertEqual(request.task.originalRequest?.httpMethod, adapter.method.rawValue)
  208. }
  209. func testThatSessionManagerCallsRequestAdapterWhenCreatingUploadRequestWithFile() {
  210. // Given
  211. let adapter = HTTPMethodAdapter(method: .get)
  212. let sessionManager = SessionManager()
  213. sessionManager.adapter = adapter
  214. sessionManager.startRequestsImmediately = false
  215. // When
  216. let fileURL = URL(fileURLWithPath: "/path/to/some/file.txt")
  217. let request = sessionManager.upload(fileURL, to: "https://httpbin.org/post", withMethod: .post)
  218. // Then
  219. XCTAssertEqual(request.task.originalRequest?.httpMethod, adapter.method.rawValue)
  220. }
  221. func testThatSessionManagerCallsRequestAdapterWhenCreatingUploadRequestWithInputStream() {
  222. // Given
  223. let adapter = HTTPMethodAdapter(method: .get)
  224. let sessionManager = SessionManager()
  225. sessionManager.adapter = adapter
  226. sessionManager.startRequestsImmediately = false
  227. // When
  228. let inputStream = InputStream(data: "data".data(using: .utf8)!)
  229. let request = sessionManager.upload(inputStream, to: "https://httpbin.org/post", withMethod: .post)
  230. // Then
  231. XCTAssertEqual(request.task.originalRequest?.httpMethod, adapter.method.rawValue)
  232. }
  233. }
  234. // MARK: -
  235. class SessionManagerConfigurationHeadersTestCase: BaseTestCase {
  236. enum ConfigurationType {
  237. case `default`, ephemeral, background
  238. }
  239. func testThatDefaultConfigurationHeadersAreSentWithRequest() {
  240. // Given, When, Then
  241. executeAuthorizationHeaderTest(for: .default)
  242. }
  243. func testThatEphemeralConfigurationHeadersAreSentWithRequest() {
  244. // Given, When, Then
  245. executeAuthorizationHeaderTest(for: .ephemeral)
  246. }
  247. // ⚠️ This test has been removed as a result of rdar://26870455 in Xcode 8 Seed 1
  248. // func testThatBackgroundConfigurationHeadersAreSentWithRequest() {
  249. // // Given, When, Then
  250. // executeAuthorizationHeaderTest(for: .background)
  251. // }
  252. private func executeAuthorizationHeaderTest(for type: ConfigurationType) {
  253. // Given
  254. let manager: SessionManager = {
  255. let configuration: URLSessionConfiguration = {
  256. let configuration: URLSessionConfiguration
  257. switch type {
  258. case .default:
  259. configuration = .default
  260. case .ephemeral:
  261. configuration = .ephemeral
  262. case .background:
  263. let identifier = "org.alamofire.test.manager-configuration-tests"
  264. configuration = .background(withIdentifier: identifier)
  265. }
  266. var headers = SessionManager.defaultHTTPHeaders
  267. headers["Authorization"] = "Bearer 123456"
  268. configuration.httpAdditionalHeaders = headers
  269. return configuration
  270. }()
  271. return SessionManager(configuration: configuration)
  272. }()
  273. let expectation = self.expectation(description: "request should complete successfully")
  274. var response: Response<Any>?
  275. // When
  276. manager.request("https://httpbin.org/headers", withMethod: .get)
  277. .responseJSON { closureResponse in
  278. response = closureResponse
  279. expectation.fulfill()
  280. }
  281. waitForExpectations(timeout: timeout, handler: nil)
  282. // Then
  283. if let response = response {
  284. XCTAssertNotNil(response.request, "request should not be nil")
  285. XCTAssertNotNil(response.response, "response should not be nil")
  286. XCTAssertNotNil(response.data, "data should not be nil")
  287. XCTAssertTrue(response.result.isSuccess, "result should be a success")
  288. // The `as NSString` cast is necessary due to a compiler bug. See the following rdar for more info.
  289. // - https://openradar.appspot.com/radar?id=5517037090635776
  290. if
  291. let headers = (response.result.value as AnyObject?)?["headers" as NSString] as? [String: String],
  292. let authorization = headers["Authorization"]
  293. {
  294. XCTAssertEqual(authorization, "Bearer 123456", "authorization header value does not match")
  295. } else {
  296. XCTFail("failed to extract authorization header value")
  297. }
  298. } else {
  299. XCTFail("response should not be nil")
  300. }
  301. }
  302. }