ソースを参照

Safer Custom rootQueues (#3523)

* Add queue targeting to convenience init.

* Formatting.

* Don't retarget the main queue.
Jon Shier 4 年 前
コミット
65b7769490
3 ファイル変更43 行追加21 行削除
  1. 5 2
      Source/Session.swift
  2. 21 0
      Tests/SessionTests.swift
  3. 17 19
      Tests/ValidationTests.swift

+ 5 - 2
Source/Session.swift

@@ -183,12 +183,15 @@ open class Session {
                             eventMonitors: [EventMonitor] = []) {
         precondition(configuration.identifier == nil, "Alamofire does not support background URLSessionConfigurations.")
 
-        let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: rootQueue, name: "org.alamofire.session.sessionDelegateQueue")
+        // Retarget the incoming rootQueue for safety, unless it's the main queue, which we know is safe.
+        let serialRootQueue = (rootQueue === DispatchQueue.main) ? rootQueue : DispatchQueue(label: rootQueue.label,
+                                                                                             target: rootQueue)
+        let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: serialRootQueue, name: "\(serialRootQueue.label).sessionDelegate")
         let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue)
 
         self.init(session: session,
                   delegate: delegate,
-                  rootQueue: rootQueue,
+                  rootQueue: serialRootQueue,
                   startRequestsImmediately: startRequestsImmediately,
                   requestQueue: requestQueue,
                   serializationQueue: serializationQueue,

+ 21 - 0
Tests/SessionTests.swift

@@ -266,6 +266,27 @@ final class SessionTestCase: BaseTestCase {
         XCTAssertNotNil(session.serverTrustManager, "session server trust policy manager should not be nil")
     }
 
+    // MARK: Tests - Parallel Root Queue
+
+    func testThatSessionWorksCorrectlyWhenPassedAConcurrentRootQueue() {
+        // Given
+        let queue = DispatchQueue(label: "ohNoAParallelQueue", attributes: .concurrent)
+        let session = Session(rootQueue: queue)
+        let didFinish = expectation(description: "request did finish")
+        var receivedResponse: TestResponse?
+
+        // When
+        session.request(.get).responseDecodable(of: TestResponse.self) { response in
+            receivedResponse = response.value
+            didFinish.fulfill()
+        }
+
+        waitForExpectations(timeout: timeout)
+
+        // Then
+        XCTAssertNotNil(receivedResponse, "Should receive TestResponse.")
+    }
+
     // MARK: Tests - Default HTTP Headers
 
     func testDefaultUserAgentHeader() {

+ 17 - 19
Tests/ValidationTests.swift

@@ -257,7 +257,7 @@ final class ContentTypeValidationTestCase: BaseTestCase {
         var requestError: AFError?
         var downloadError: AFError?
 
-        let acceptableContentTypes = [ // Sorted in a random order, not alphabetically
+        let acceptableContentTypes = [// Sorted in a random order, not alphabetically
             "application/octet-stream",
             "image/gif",
             "image/x-xbitmap",
@@ -271,8 +271,7 @@ final class ContentTypeValidationTestCase: BaseTestCase {
             "image/ico",
             "image/bmp",
             "image/x-ms-bmp",
-            "image/x-win-bitmap"
-        ]
+            "image/x-win-bitmap"]
 
         // When
         AF.request(endpoint)
@@ -295,22 +294,21 @@ final class ContentTypeValidationTestCase: BaseTestCase {
         XCTAssertNotNil(requestError)
         XCTAssertNotNil(downloadError)
 
-        let expectedAcceptableContentTypes = [ // Sorted in a specific order, alphabetically
-             "application/octet-stream",
-             "image/bmp",
-             "image/gif",
-             "image/ico",
-             "image/jp2",
-             "image/jpeg",
-             "image/jpg",
-             "image/png",
-             "image/tiff",
-             "image/x-bmp",
-             "image/x-icon",
-             "image/x-ms-bmp",
-             "image/x-win-bitmap",
-             "image/x-xbitmap",
-         ]
+        let expectedAcceptableContentTypes = [// Sorted in a specific order, alphabetically
+            "application/octet-stream",
+            "image/bmp",
+            "image/gif",
+            "image/ico",
+            "image/jp2",
+            "image/jpeg",
+            "image/jpg",
+            "image/png",
+            "image/tiff",
+            "image/x-bmp",
+            "image/x-icon",
+            "image/x-ms-bmp",
+            "image/x-win-bitmap",
+            "image/x-xbitmap"]
 
         for error in [requestError, downloadError] {
             XCTAssertEqual(error?.isUnacceptableContentType, true)