From f2db5625d99470e676591c78eb876f1344368339 Mon Sep 17 00:00:00 2001 From: Adam Sousa <74457057+adamsousa@users.noreply.github.com> Date: Wed, 14 Dec 2022 05:08:31 -0500 Subject: [PATCH] KTOR-5332 Fixes iOS unit test deadlock occurring with DarwinClientEngine (#3291) --- .../engine/darwin/DarwinLegacyClientEngine.kt | 2 +- .../darwin/internal/DarwinLegacySession.kt | 4 ++-- .../darwin/test/DarwinLegacyEngineTest.kt | 17 ++++++++------- .../engine/darwin/DarwinClientEngine.kt | 2 +- .../engine/darwin/internal/DarwinSession.kt | 4 ++-- .../darwin/test/DarwinEngineTest.kt | 21 +++++++++++-------- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/DarwinLegacyClientEngine.kt b/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/DarwinLegacyClientEngine.kt index 791ef573c78..637f852f92a 100644 --- a/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/DarwinLegacyClientEngine.kt +++ b/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/DarwinLegacyClientEngine.kt @@ -16,7 +16,7 @@ import platform.Foundation.* internal class DarwinLegacyClientEngine( override val config: DarwinLegacyClientEngineConfig ) : HttpClientEngineBase("ktor-darwin-legacy") { - private val requestQueue = NSOperationQueue() + private val requestQueue: NSOperationQueue? = NSOperationQueue.currentQueue() override val dispatcher = Dispatchers.Unconfined diff --git a/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/internal/DarwinLegacySession.kt b/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/internal/DarwinLegacySession.kt index b49cb5ed9ea..d05f82cb52b 100644 --- a/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/internal/DarwinLegacySession.kt +++ b/ktor-client/ktor-client-darwin-legacy/darwin/src/io/ktor/client/engine/darwin/internal/DarwinLegacySession.kt @@ -13,7 +13,7 @@ import kotlin.coroutines.* @OptIn(UnsafeNumber::class) internal class DarwinLegacySession( private val config: DarwinLegacyClientEngineConfig, - private val requestQueue: NSOperationQueue + private val requestQueue: NSOperationQueue? ) : Closeable { private val closed = atomic(false) @@ -47,7 +47,7 @@ internal class DarwinLegacySession( @OptIn(UnsafeNumber::class) internal fun createSession( config: DarwinLegacyClientEngineConfig, - requestQueue: NSOperationQueue + requestQueue: NSOperationQueue? ): Pair { val configuration = NSURLSessionConfiguration.defaultSessionConfiguration().apply { setupProxy(config) diff --git a/ktor-client/ktor-client-darwin-legacy/darwin/test/DarwinLegacyEngineTest.kt b/ktor-client/ktor-client-darwin-legacy/darwin/test/DarwinLegacyEngineTest.kt index 8eca63effa8..64629cd409b 100644 --- a/ktor-client/ktor-client-darwin-legacy/darwin/test/DarwinLegacyEngineTest.kt +++ b/ktor-client/ktor-client-darwin-legacy/darwin/test/DarwinLegacyEngineTest.kt @@ -8,6 +8,7 @@ import io.ktor.http.* import kotlinx.coroutines.* import platform.Foundation.* import platform.Foundation.NSHTTPCookieStorage.Companion.sharedHTTPCookieStorage +import kotlin.coroutines.CoroutineContext import kotlin.test.* /* @@ -16,8 +17,10 @@ import kotlin.test.* class DarwinLegacyEngineTest { + val testCoroutineContext: CoroutineContext = Dispatchers.Default + @Test - fun testRequestInRunBlocking() = runBlocking { + fun testRequestInRunBlocking() = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) try { @@ -31,7 +34,7 @@ class DarwinLegacyEngineTest { } @Test - fun testQueryWithCyrillic() = runBlocking { + fun testQueryWithCyrillic() = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) try { @@ -45,7 +48,7 @@ class DarwinLegacyEngineTest { } @Test - fun testQueryWithMultipleParams() = runBlocking { + fun testQueryWithMultipleParams() = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) try { @@ -72,7 +75,7 @@ class DarwinLegacyEngineTest { } @Test - fun testCookieIsNotPersistedByDefault() = runBlocking { + fun testCookieIsNotPersistedByDefault() = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) try { client.get("$TEST_SERVER/cookies") @@ -86,7 +89,7 @@ class DarwinLegacyEngineTest { } @Test - fun testCookiePersistedWithSessionStore() = runBlocking { + fun testCookiePersistedWithSessionStore() = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) { engine { configureSession { @@ -107,7 +110,7 @@ class DarwinLegacyEngineTest { } @Test - fun testOverrideDefaultSession(): Unit = runBlocking { + fun testOverrideDefaultSession(): Unit = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) { val delegate = KtorLegacyNSURLSessionDelegate() val session = NSURLSession.sessionWithConfiguration( @@ -129,7 +132,7 @@ class DarwinLegacyEngineTest { } @Test - fun testConfigureRequest(): Unit = runBlocking { + fun testConfigureRequest(): Unit = runBlocking(testCoroutineContext) { val client = HttpClient(DarwinLegacy) { engine { configureRequest { diff --git a/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/DarwinClientEngine.kt b/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/DarwinClientEngine.kt index bba128684a9..7d071a32b15 100644 --- a/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/DarwinClientEngine.kt +++ b/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/DarwinClientEngine.kt @@ -18,7 +18,7 @@ import kotlin.coroutines.* @OptIn(InternalAPI::class) internal class DarwinClientEngine(override val config: DarwinClientEngineConfig) : HttpClientEngineBase("ktor-darwin") { - private val requestQueue = NSOperationQueue() + private val requestQueue: NSOperationQueue? = NSOperationQueue.currentQueue() override val dispatcher = Dispatchers.Unconfined diff --git a/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinSession.kt b/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinSession.kt index b822a5feadf..e1c3605fdf5 100644 --- a/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinSession.kt +++ b/ktor-client/ktor-client-darwin/darwin/src/io/ktor/client/engine/darwin/internal/DarwinSession.kt @@ -13,7 +13,7 @@ import kotlin.coroutines.* @OptIn(UnsafeNumber::class) internal class DarwinSession( private val config: DarwinClientEngineConfig, - requestQueue: NSOperationQueue + requestQueue: NSOperationQueue? ) : Closeable { private val closed = atomic(false) @@ -54,7 +54,7 @@ internal class DarwinSession( @OptIn(UnsafeNumber::class) internal fun createSession( config: DarwinClientEngineConfig, - requestQueue: NSOperationQueue + requestQueue: NSOperationQueue? ): Pair { val configuration = NSURLSessionConfiguration.defaultSessionConfiguration().apply { setupProxy(config) diff --git a/ktor-client/ktor-client-darwin/darwin/test/DarwinEngineTest.kt b/ktor-client/ktor-client-darwin/darwin/test/DarwinEngineTest.kt index e14fa102fc1..38666ce9862 100644 --- a/ktor-client/ktor-client-darwin/darwin/test/DarwinEngineTest.kt +++ b/ktor-client/ktor-client-darwin/darwin/test/DarwinEngineTest.kt @@ -11,6 +11,7 @@ import kotlinx.cinterop.* import kotlinx.coroutines.* import platform.Foundation.* import platform.Foundation.NSHTTPCookieStorage.Companion.sharedHTTPCookieStorage +import kotlin.coroutines.CoroutineContext import kotlin.test.* /* @@ -19,8 +20,10 @@ import kotlin.test.* class DarwinEngineTest { + val testCoroutineContext: CoroutineContext = Dispatchers.Default + @Test - fun testRequestInRunBlocking() = runBlocking { + fun testRequestInRunBlocking() = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) try { @@ -34,7 +37,7 @@ class DarwinEngineTest { } @Test - fun testQueryWithCyrillic() = runBlocking { + fun testQueryWithCyrillic() = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) try { @@ -48,7 +51,7 @@ class DarwinEngineTest { } @Test - fun testQueryWithMultipleParams() = runBlocking { + fun testQueryWithMultipleParams() = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) try { @@ -75,7 +78,7 @@ class DarwinEngineTest { } @Test - fun testCookieIsNotPersistedByDefault() = runBlocking { + fun testCookieIsNotPersistedByDefault() = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) try { client.get("$TEST_SERVER/cookies") @@ -89,7 +92,7 @@ class DarwinEngineTest { } @Test - fun testCookiePersistedWithSessionStore() = runBlocking { + fun testCookiePersistedWithSessionStore() = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) { engine { configureSession { @@ -110,7 +113,7 @@ class DarwinEngineTest { } @Test - fun testOverrideDefaultSession(): Unit = runBlocking { + fun testOverrideDefaultSession(): Unit = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) { val delegate = KtorNSURLSessionDelegate() val session = NSURLSession.sessionWithConfiguration( @@ -132,7 +135,7 @@ class DarwinEngineTest { } @Test - fun testOverrideDefaultSessionWithWebSockets(): Unit = runBlocking { + fun testOverrideDefaultSessionWithWebSockets(): Unit = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) { val delegate = KtorNSURLSessionDelegate() val session = NSURLSession.sessionWithConfiguration( @@ -158,7 +161,7 @@ class DarwinEngineTest { } @Test - fun testConfigureRequest(): Unit = runBlocking { + fun testConfigureRequest(): Unit = runBlocking(testCoroutineContext) { val client = HttpClient(Darwin) { engine { configureRequest { @@ -174,7 +177,7 @@ class DarwinEngineTest { @OptIn(UnsafeNumber::class) @Test - fun testConfigureWebsocketRequest(): Unit = runBlocking { + fun testConfigureWebsocketRequest(): Unit = runBlocking(testCoroutineContext) { var customChallengeCalled = false val client = HttpClient(Darwin) { engine {