From 0fd6b825bd464bb1b2123a54a552e6244d8ffa91 Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 15:02:25 -0800 Subject: [PATCH 01/10] create intermediate supportedTargetMain and supportedTargetTest sourcesets goes between common and js/apple --- kmp-nativecoroutines-core/build.gradle.kts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/kmp-nativecoroutines-core/build.gradle.kts b/kmp-nativecoroutines-core/build.gradle.kts index 93a30d57..1857f7b0 100644 --- a/kmp-nativecoroutines-core/build.gradle.kts +++ b/kmp-nativecoroutines-core/build.gradle.kts @@ -37,12 +37,18 @@ kotlin { implementation(kotlin("test")) } } - val appleMain by creating { + val supportedTargetMain by creating { dependsOn(commonMain) } - val appleTest by creating { + val supportedTargetTest by creating { dependsOn(commonTest) } + val appleMain by creating { + dependsOn(supportedTargetMain) + } + val appleTest by creating { + dependsOn(supportedTargetTest) + } listOf( macosX64, macosArm64, iosArm64, iosX64, iosSimulatorArm64, @@ -56,5 +62,11 @@ kotlin { dependsOn(appleTest) } } + val jsMain by getting { + dependsOn(supportedTargetMain) + } + val jsTest by getting { + dependsOn(supportedTargetTest) + } } } From 277e555ea1b248cbcd9ea7914404f5f38363f51e Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 15:03:55 -0800 Subject: [PATCH 02/10] create cross-platform freeze function --- .../com/rickclephas/kmp/nativecoroutines/FreezingApple.kt | 5 +++++ .../com/rickclephas/kmp/nativecoroutines/FreezingJs.kt | 6 ++++++ .../kotlin/com/rickclephas/kmp/nativecoroutines/Freezing.kt | 3 +++ 3 files changed, 14 insertions(+) create mode 100644 kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingApple.kt create mode 100644 kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingJs.kt create mode 100644 kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/Freezing.kt diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingApple.kt b/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingApple.kt new file mode 100644 index 00000000..a14b4d5f --- /dev/null +++ b/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingApple.kt @@ -0,0 +1,5 @@ +package com.rickclephas.kmp.nativecoroutines + +import kotlin.native.concurrent.freeze + +actual fun T.freeze(): T = this.freeze() diff --git a/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingJs.kt b/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingJs.kt new file mode 100644 index 00000000..7e3457c4 --- /dev/null +++ b/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/FreezingJs.kt @@ -0,0 +1,6 @@ +package com.rickclephas.kmp.nativecoroutines + +/** + * Freezing is a no-op on JS + */ +internal actual fun T.freeze() = this \ No newline at end of file diff --git a/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/Freezing.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/Freezing.kt new file mode 100644 index 00000000..34768f34 --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/Freezing.kt @@ -0,0 +1,3 @@ +package com.rickclephas.kmp.nativecoroutines + +internal expect fun T.freeze(): T From 1473310b154057045a4177ad1c903e1fa6c4a6d0 Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 15:04:30 -0800 Subject: [PATCH 03/10] create cross-platform PlatformError abstraction --- .../com/rickclephas/kmp/nativecoroutines/NSError.kt | 7 +++++++ .../kmp/nativecoroutines/PlatformErrorJs.kt | 6 ++++++ .../kmp/nativecoroutines/PlatformError.kt | 13 +++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformErrorJs.kt create mode 100644 kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformError.kt diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NSError.kt b/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NSError.kt index 2b91a447..89d26484 100644 --- a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NSError.kt +++ b/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NSError.kt @@ -6,6 +6,13 @@ import platform.Foundation.NSError import platform.Foundation.NSLocalizedDescriptionKey import kotlin.native.concurrent.freeze +actual typealias PlatformError = NSError + +internal actual fun Throwable.asPlatformError(): PlatformError = this.asNSError() + +actual val PlatformError.kotlinCause + get() = this.userInfo["KotlinException"] as? Throwable + /** * Converts a [Throwable] to a [NSError]. * diff --git a/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformErrorJs.kt b/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformErrorJs.kt new file mode 100644 index 00000000..5e503688 --- /dev/null +++ b/kmp-nativecoroutines-core/src/jsMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformErrorJs.kt @@ -0,0 +1,6 @@ +package com.rickclephas.kmp.nativecoroutines + +actual typealias PlatformError = Throwable +actual fun Throwable.asPlatformError() = this +actual val PlatformError.kotlinCause: Throwable? + get() = this \ No newline at end of file diff --git a/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformError.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformError.kt new file mode 100644 index 00000000..c6a8faa6 --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/PlatformError.kt @@ -0,0 +1,13 @@ +package com.rickclephas.kmp.nativecoroutines + +/** + * Represents an error in a way that the specific platform is able to handle + */ +expect class PlatformError + +/** + * Converts a [Throwable] to a [PlatformError]. + */ +internal expect fun Throwable.asPlatformError(): PlatformError + +internal expect val PlatformError.kotlinCause: Throwable? \ No newline at end of file From 7d3dd7bc03c28e60d36fe2de0b0df2870488b4cc Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 15:05:48 -0800 Subject: [PATCH 04/10] move core classes from appleMain to supportedTargetMain --- .../rickclephas/kmp/nativecoroutines/CoroutineScope.kt | 0 .../rickclephas/kmp/nativecoroutines/NativeCallback.kt | 2 -- .../kmp/nativecoroutines/NativeCancellable.kt | 1 - .../com/rickclephas/kmp/nativecoroutines/NativeFlow.kt | 10 ++++------ .../rickclephas/kmp/nativecoroutines/NativeSuspend.kt | 10 ++++------ 5 files changed, 8 insertions(+), 15 deletions(-) rename kmp-nativecoroutines-core/src/{appleMain => supportedTargetMain}/kotlin/com/rickclephas/kmp/nativecoroutines/CoroutineScope.kt (100%) rename kmp-nativecoroutines-core/src/{appleMain => supportedTargetMain}/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt (92%) rename kmp-nativecoroutines-core/src/{appleMain => supportedTargetMain}/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt (91%) rename kmp-nativecoroutines-core/src/{appleMain => supportedTargetMain}/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt (87%) rename kmp-nativecoroutines-core/src/{appleMain => supportedTargetMain}/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt (87%) diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/CoroutineScope.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/CoroutineScope.kt similarity index 100% rename from kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/CoroutineScope.kt rename to kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/CoroutineScope.kt diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt similarity index 92% rename from kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt rename to kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt index 18390787..1aef03d0 100644 --- a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallback.kt @@ -1,7 +1,5 @@ package com.rickclephas.kmp.nativecoroutines -import kotlin.native.concurrent.freeze - /** * A callback with a single argument. * diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt similarity index 91% rename from kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt rename to kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt index c0786d83..d3262256 100644 --- a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellable.kt @@ -1,7 +1,6 @@ package com.rickclephas.kmp.nativecoroutines import kotlinx.coroutines.Job -import kotlin.native.concurrent.freeze /** * A function that cancels the coroutines [Job]. diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt similarity index 87% rename from kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt rename to kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt index f1dce7e6..a682a210 100644 --- a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlow.kt @@ -5,8 +5,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch -import platform.Foundation.NSError -import kotlin.native.concurrent.freeze /** * A function that collects a [Flow] via callbacks. @@ -14,7 +12,7 @@ import kotlin.native.concurrent.freeze * The function takes an `onItem` and `onComplete` callback * and returns a cancellable that can be used to cancel the collection. */ -typealias NativeFlow = (onItem: NativeCallback, onComplete: NativeCallback) -> NativeCancellable +typealias NativeFlow = (onItem: NativeCallback, onComplete: NativeCallback) -> NativeCancellable /** * Creates a [NativeFlow] for this [Flow]. @@ -25,7 +23,7 @@ typealias NativeFlow = (onItem: NativeCallback, onComplete: NativeCallback */ fun Flow.asNativeFlow(scope: CoroutineScope? = null): NativeFlow { val coroutineScope = scope ?: defaultCoroutineScope - return (collect@{ onItem: NativeCallback, onComplete: NativeCallback -> + return (collect@{ onItem: NativeCallback, onComplete: NativeCallback -> val job = coroutineScope.launch { try { collect { onItem(it) } @@ -35,13 +33,13 @@ fun Flow.asNativeFlow(scope: CoroutineScope? = null): NativeFlow { // this is required since the job could be cancelled before it is started throw e } catch (e: Throwable) { - onComplete(e.asNSError()) + onComplete(e.asPlatformError()) } } job.invokeOnCompletion { cause -> // Only handle CancellationExceptions, all other exceptions should be handled inside the job if (cause !is CancellationException) return@invokeOnCompletion - onComplete(cause.asNSError()) + onComplete(cause.asPlatformError()) } return@collect job.asNativeCancellable() }).freeze() diff --git a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt similarity index 87% rename from kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt rename to kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt index 676b38ca..9da1315a 100644 --- a/kmp-nativecoroutines-core/src/appleMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetMain/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspend.kt @@ -3,8 +3,6 @@ package com.rickclephas.kmp.nativecoroutines import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -import platform.Foundation.NSError -import kotlin.native.concurrent.freeze /** * A function that awaits a suspend function via callbacks. @@ -12,7 +10,7 @@ import kotlin.native.concurrent.freeze * The function takes an `onResult` and `onError` callback * and returns a cancellable that can be used to cancel the suspend function. */ -typealias NativeSuspend = (onResult: NativeCallback, onError: NativeCallback) -> NativeCancellable +typealias NativeSuspend = (onResult: NativeCallback, onError: NativeCallback) -> NativeCancellable /** * Creates a [NativeSuspend] for the provided suspend [block]. @@ -22,7 +20,7 @@ typealias NativeSuspend = (onResult: NativeCallback, onError: NativeCallba */ fun nativeSuspend(scope: CoroutineScope? = null, block: suspend () -> T): NativeSuspend { val coroutineScope = scope ?: defaultCoroutineScope - return (collect@{ onResult: NativeCallback, onError: NativeCallback -> + return (collect@{ onResult: NativeCallback, onError: NativeCallback -> val job = coroutineScope.launch { try { onResult(block()) @@ -31,13 +29,13 @@ fun nativeSuspend(scope: CoroutineScope? = null, block: suspend () -> T): Na // this is required since the job could be cancelled before it is started throw e } catch (e: Throwable) { - onError(e.asNSError()) + onError(e.asPlatformError()) } } job.invokeOnCompletion { cause -> // Only handle CancellationExceptions, all other exceptions should be handled inside the job if (cause !is CancellationException) return@invokeOnCompletion - onError(cause.asNSError()) + onError(cause.asPlatformError()) } return@collect job.asNativeCancellable() }).freeze() From f886f267ea92383d698685491be98f68d0cb9df8 Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 15:14:16 -0800 Subject: [PATCH 05/10] add dependency on kotlinx-coroutines-test --- buildSrc/src/main/kotlin/Dependencies.kt | 1 + kmp-nativecoroutines-core/build.gradle.kts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 9f01535f..db27a604 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -9,5 +9,6 @@ object Dependencies { object Kotlinx { const val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt" + const val coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0-native-mt" } } \ No newline at end of file diff --git a/kmp-nativecoroutines-core/build.gradle.kts b/kmp-nativecoroutines-core/build.gradle.kts index 1857f7b0..4bb41435 100644 --- a/kmp-nativecoroutines-core/build.gradle.kts +++ b/kmp-nativecoroutines-core/build.gradle.kts @@ -35,6 +35,8 @@ kotlin { val commonTest by getting { dependencies { implementation(kotlin("test")) + + implementation(Dependencies.Kotlinx.coroutinesTest) } } val supportedTargetMain by creating { From 6da86897621702ba62fb4085ccef728a4b5c2091 Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 21:32:00 -0800 Subject: [PATCH 06/10] wip: rename tests in appleTest to Apple* --- .../{NativeCallbackTests.kt => AppleNativeCallbackTests.kt} | 2 +- ...NativeCancellableTests.kt => AppleNativeCancellableTests.kt} | 2 +- .../{NativeFlowTests.kt => AppleNativeFlowTests.kt} | 2 +- .../{NativeSuspendTests.kt => AppleNativeSuspendTests.kt} | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/{NativeCallbackTests.kt => AppleNativeCallbackTests.kt} (97%) rename kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/{NativeCancellableTests.kt => AppleNativeCancellableTests.kt} (96%) rename kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/{NativeFlowTests.kt => AppleNativeFlowTests.kt} (99%) rename kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/{NativeSuspendTests.kt => AppleNativeSuspendTests.kt} (99%) diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCallbackTests.kt similarity index 97% rename from kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt rename to kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCallbackTests.kt index e4643c50..e0b1a0dd 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCallbackTests.kt @@ -3,7 +3,7 @@ package com.rickclephas.kmp.nativecoroutines import kotlin.native.concurrent.isFrozen import kotlin.test.* -class NativeCallbackTests { +class AppleNativeCallbackTests { @Test fun `ensure frozen`() { diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCancellableTests.kt similarity index 96% rename from kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt rename to kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCancellableTests.kt index cac82616..09d717ae 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeCancellableTests.kt @@ -6,7 +6,7 @@ import kotlin.test.Test import kotlin.test.assertFalse import kotlin.test.assertTrue -class NativeCancellableTests { +class AppleNativeCancellableTests { @Test fun `ensure frozen`() { diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt similarity index 99% rename from kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt rename to kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt index ce5dce3f..eed323c2 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt @@ -7,7 +7,7 @@ import kotlin.native.concurrent.AtomicInt import kotlin.native.concurrent.isFrozen import kotlin.test.* -class NativeFlowTests { +class AppleNativeFlowTests { @Test fun `ensure frozen`() { diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt similarity index 99% rename from kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt rename to kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt index 40d14a7d..5da675f0 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt @@ -9,7 +9,7 @@ import kotlin.native.concurrent.AtomicInt import kotlin.native.concurrent.isFrozen import kotlin.test.* -class NativeSuspendTests { +class AppleNativeSuspendTests { private suspend fun delayAndReturn(delay: Long, value: RandomValue): RandomValue { delay(delay) From 2718223cdd378d08e1469ee6c7b9188ad882b9cf Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 21:33:48 -0800 Subject: [PATCH 07/10] use kotlinCause method in apple tests --- .../rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt | 4 ++-- .../kmp/nativecoroutines/AppleNativeSuspendTests.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt index eed323c2..ca262b49 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt @@ -41,7 +41,7 @@ class AppleNativeFlowTests { val completionCount = AtomicInt(0) nativeFlow({ _, _ -> }, { error, _ -> assertNotNull(error, "Flow should complete with an error") - val kotlinException = error.userInfo["KotlinException"] + val kotlinException = error.kotlinCause assertSame(exception, kotlinException, "Kotlin exception should be the same exception") completionCount.increment() }) @@ -72,7 +72,7 @@ class AppleNativeFlowTests { val completionCount = AtomicInt(0) val cancel = nativeFlow({ _, _ -> }, { error, _ -> assertNotNull(error, "Flow should complete with an error") - val exception = error.userInfo["KotlinException"] + val exception = error.kotlinCause assertIs(exception, "Error should contain CancellationException") completionCount.increment() }) diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt index 5da675f0..7a7c35d2 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt @@ -59,7 +59,7 @@ class AppleNativeSuspendTests { receivedResultCount.increment() }, { error, _ -> assertNotNull(error, "Function should complete with an error") - val kotlinException = error.userInfo["KotlinException"] + val kotlinException = error.kotlinCause assertSame(exception, kotlinException, "Kotlin exception should be the same exception") receivedErrorCount.increment() }) @@ -78,7 +78,7 @@ class AppleNativeSuspendTests { receivedResultCount.increment() }, { error, _ -> assertNotNull(error, "Function should complete with an error") - val exception = error.userInfo["KotlinException"] + val exception = error.kotlinCause assertIs(exception, "Error should contain CancellationException") receivedErrorCount.increment() }) From fc42913db0d85b25013ba78ebe976708752bf78e Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 21:42:49 -0800 Subject: [PATCH 08/10] use AtomicInt from kotlinfu instead of kotlin native --- buildSrc/src/main/kotlin/Dependencies.kt | 2 ++ kmp-nativecoroutines-core/build.gradle.kts | 1 + .../nativecoroutines/AppleNativeFlowTests.kt | 18 ++++++------- .../AppleNativeSuspendTests.kt | 26 +++++++++---------- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index db27a604..63fdb82d 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -10,5 +10,7 @@ object Dependencies { object Kotlinx { const val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt" const val coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0-native-mt" + + const val atomicfu = "org.jetbrains.kotlinx:atomicfu:0.17.1" } } \ No newline at end of file diff --git a/kmp-nativecoroutines-core/build.gradle.kts b/kmp-nativecoroutines-core/build.gradle.kts index 4bb41435..2d213faf 100644 --- a/kmp-nativecoroutines-core/build.gradle.kts +++ b/kmp-nativecoroutines-core/build.gradle.kts @@ -37,6 +37,7 @@ kotlin { implementation(kotlin("test")) implementation(Dependencies.Kotlinx.coroutinesTest) + implementation(Dependencies.Kotlinx.atomicfu) } } val supportedTargetMain by creating { diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt index ca262b49..98ff43b5 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeFlowTests.kt @@ -1,9 +1,9 @@ package com.rickclephas.kmp.nativecoroutines +import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.flow -import kotlin.native.concurrent.AtomicInt import kotlin.native.concurrent.isFrozen import kotlin.test.* @@ -23,10 +23,10 @@ class AppleNativeFlowTests { val flow = flow { } val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) - val completionCount = AtomicInt(0) + val completionCount = atomic(0) nativeFlow({ _, _ -> }, { error, _ -> assertNull(error, "Flow should complete without an error") - completionCount.increment() + completionCount.incrementAndGet() }) job.children.forEach { it.join() } // Waits for the collection to complete assertEquals(1, completionCount.value, "Completion callback should be called once") @@ -38,12 +38,12 @@ class AppleNativeFlowTests { val flow = flow { throw exception } val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) - val completionCount = AtomicInt(0) + val completionCount = atomic(0) nativeFlow({ _, _ -> }, { error, _ -> assertNotNull(error, "Flow should complete with an error") val kotlinException = error.kotlinCause assertSame(exception, kotlinException, "Kotlin exception should be the same exception") - completionCount.increment() + completionCount.incrementAndGet() }) job.children.forEach { it.join() } // Waits for the collection to complete assertEquals(1, completionCount.value, "Completion callback should be called once") @@ -55,10 +55,10 @@ class AppleNativeFlowTests { val flow = flow { values.forEach { emit(it) } } val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) - val receivedValueCount = AtomicInt(0) + val receivedValueCount = atomic(0) nativeFlow({ value, _ -> assertSame(values[receivedValueCount.value], value, "Received incorrect value") - receivedValueCount.increment() + receivedValueCount.incrementAndGet() }, { _, _ -> }) job.children.forEach { it.join() } // Waits for the collection to complete assertEquals(values.size, receivedValueCount.value, "Item callback should be called for every value") @@ -69,12 +69,12 @@ class AppleNativeFlowTests { val flow = MutableSharedFlow() val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) - val completionCount = AtomicInt(0) + val completionCount = atomic(0) val cancel = nativeFlow({ _, _ -> }, { error, _ -> assertNotNull(error, "Flow should complete with an error") val exception = error.kotlinCause assertIs(exception, "Error should contain CancellationException") - completionCount.increment() + completionCount.incrementAndGet() }) delay(100) // Gives the collection some time to start cancel() diff --git a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt index 7a7c35d2..31e9d120 100644 --- a/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt +++ b/kmp-nativecoroutines-core/src/appleTest/kotlin/com/rickclephas/kmp/nativecoroutines/AppleNativeSuspendTests.kt @@ -1,11 +1,11 @@ package com.rickclephas.kmp.nativecoroutines +import kotlinx.atomicfu.atomic import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import kotlin.coroutines.cancellation.CancellationException -import kotlin.native.concurrent.AtomicInt import kotlin.native.concurrent.isFrozen import kotlin.test.* @@ -35,13 +35,13 @@ class AppleNativeSuspendTests { val value = RandomValue() val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(100, value) } - val receivedResultCount = AtomicInt(0) - val receivedErrorCount = AtomicInt(0) + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) nativeSuspend({ receivedValue, _ -> assertSame(value, receivedValue, "Received incorrect value") - receivedResultCount.increment() + receivedResultCount.incrementAndGet() }, { _, _ -> - receivedErrorCount.increment() + receivedErrorCount.incrementAndGet() }) job.children.forEach { it.join() } // Waits for the function to complete assertEquals(1, receivedResultCount.value, "Result callback should be called once") @@ -53,15 +53,15 @@ class AppleNativeSuspendTests { val exception = RandomException() val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndThrow(100, exception) } - val receivedResultCount = AtomicInt(0) - val receivedErrorCount = AtomicInt(0) + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) nativeSuspend({ _, _ -> - receivedResultCount.increment() + receivedResultCount.incrementAndGet() }, { error, _ -> assertNotNull(error, "Function should complete with an error") val kotlinException = error.kotlinCause assertSame(exception, kotlinException, "Kotlin exception should be the same exception") - receivedErrorCount.increment() + receivedErrorCount.incrementAndGet() }) job.children.forEach { it.join() } // Waits for the function to complete assertEquals(1, receivedErrorCount.value, "Error callback should be called once") @@ -72,15 +72,15 @@ class AppleNativeSuspendTests { fun `ensure function is cancelled`() = runBlocking { val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(5_000, RandomValue()) } - val receivedResultCount = AtomicInt(0) - val receivedErrorCount = AtomicInt(0) + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) val cancel = nativeSuspend({ _, _ -> - receivedResultCount.increment() + receivedResultCount.incrementAndGet() }, { error, _ -> assertNotNull(error, "Function should complete with an error") val exception = error.kotlinCause assertIs(exception, "Error should contain CancellationException") - receivedErrorCount.increment() + receivedErrorCount.incrementAndGet() }) delay(100) // Gives the function some time to start cancel() From d7102686700e04a9a3fdf6e98808f50eda08fa6a Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 21:33:07 -0800 Subject: [PATCH 09/10] wip: copy apple tests into supportedTarget sourceset - replace backtick/space method names - remove tests for freezing --- .../nativecoroutines/NativeCallbackTests.kt | 21 +++++ .../NativeCancellableTests.kt | 17 ++++ .../kmp/nativecoroutines/NativeFlowTests.kt | 73 +++++++++++++++++ .../nativecoroutines/NativeSuspendTests.kt | 81 +++++++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt create mode 100644 kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt create mode 100644 kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt create mode 100644 kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt new file mode 100644 index 00000000..a7803195 --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCallbackTests.kt @@ -0,0 +1,21 @@ +package com.rickclephas.kmp.nativecoroutines + +import kotlin.test.* + +class NativeCallbackTests { + @Test + fun ensure_invoked() { + var invokeCount = 0 + var receivedValue: RandomValue? = null + val callback: NativeCallback = callback@{ value, unit -> + receivedValue = value + invokeCount++ + // This isn't required in Kotlin but it is in Swift so we'll test it anyway + return@callback unit + } + val value = RandomValue() + callback(value) + assertEquals(1, invokeCount, "NativeCallback should have been invoked once") + assertSame(value, receivedValue, "Received value should be the same as the send value") + } +} \ No newline at end of file diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt new file mode 100644 index 00000000..a8f32270 --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeCancellableTests.kt @@ -0,0 +1,17 @@ +package com.rickclephas.kmp.nativecoroutines + +import kotlinx.coroutines.Job +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class NativeCancellableTests { + @Test + fun ensure_that_the_job_gets_cancelled() { + val job = Job() + val nativeCancellable = job.asNativeCancellable() + assertFalse(job.isCancelled, "Job shouldn't be cancelled yet") + nativeCancellable() + assertTrue(job.isCancelled, "Job should be cancelled") + } +} \ No newline at end of file diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt new file mode 100644 index 00000000..cd20c3fb --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt @@ -0,0 +1,73 @@ +package com.rickclephas.kmp.nativecoroutines + +import kotlinx.atomicfu.atomic +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.flow +import kotlin.test.* + +class NativeFlowTests { + @Test + fun ensure_completion_callback_is_invoked() = runBlocking { + val flow = flow { } + val job = Job() + val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) + val completionCount = atomic(0) + nativeFlow({ _, _ -> }, { error, _ -> + assertNull(error, "Flow should complete without an error") + completionCount.incrementAndGet() + }) + job.children.forEach { it.join() } // Waits for the collection to complete + assertEquals(1, completionCount.value, "Completion callback should be called once") + } + + @Test + fun ensure_exceptions_are_received_as_errors() = runBlocking { + val exception = RandomException() + val flow = flow { throw exception } + val job = Job() + val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) + val completionCount = atomic(0) + nativeFlow({ _, _ -> }, { error, _ -> + assertNotNull(error, "Flow should complete with an error") + val kotlinException = error.kotlinCause + assertSame(exception, kotlinException, "Kotlin exception should be the same exception") + completionCount.incrementAndGet() + }) + job.children.forEach { it.join() } // Waits for the collection to complete + assertEquals(1, completionCount.value, "Completion callback should be called once") + } + + @Test + fun ensure_values_are_received() = runBlocking { + val values = listOf(RandomValue(), RandomValue(), RandomValue(), RandomValue()) + val flow = flow { values.forEach { emit(it) } } + val job = Job() + val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) + val receivedValueCount = atomic(0) + nativeFlow({ value, _ -> + assertSame(values[receivedValueCount.value], value, "Received incorrect value") + receivedValueCount.incrementAndGet() + }, { _, _ -> }) + job.children.forEach { it.join() } // Waits for the collection to complete + assertEquals(values.size, receivedValueCount.value, "Item callback should be called for every value") + } + + @Test + fun ensure_collection_is_cancelled() = runBlocking { + val flow = MutableSharedFlow() + val job = Job() + val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) + val completionCount = atomic(0) + val cancel = nativeFlow({ _, _ -> }, { error, _ -> + assertNotNull(error, "Flow should complete with an error") + val exception = error.kotlinCause + assertIs(exception, "Error should contain CancellationException") + completionCount.incrementAndGet() + }) + delay(100) // Gives the collection some time to start + cancel() + job.children.forEach { it.join() } // Waits for the collection to complete + assertEquals(1, completionCount.value, "Completion callback should be called once") + } +} \ No newline at end of file diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt new file mode 100644 index 00000000..ee4a7e91 --- /dev/null +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt @@ -0,0 +1,81 @@ +package com.rickclephas.kmp.nativecoroutines + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import kotlin.coroutines.cancellation.CancellationException +import kotlin.test.* +import kotlinx.atomicfu.atomic + +class NativeSuspendTests { + + private suspend fun delayAndReturn(delay: Long, value: RandomValue): RandomValue { + delay(delay) + return value + } + + private suspend fun delayAndThrow(delay: Long, exception: RandomException): RandomValue { + delay(delay) + throw exception + } + + @Test + fun ensure_correct_result_is_received() = runBlocking { + val value = RandomValue() + val job = Job() + val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(100, value) } + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) + nativeSuspend({ receivedValue, _ -> + assertSame(value, receivedValue, "Received incorrect value") + receivedResultCount.incrementAndGet() + }, { _, _ -> + receivedErrorCount.incrementAndGet() + }) + job.children.forEach { it.join() } // Waits for the function to complete + assertEquals(1, receivedResultCount.value, "Result callback should be called once") + assertEquals(0, receivedErrorCount.value, "Error callback shouldn't be called") + } + + @Test + fun ensure_exceptions_are_received_as_errors() = runBlocking { + val exception = RandomException() + val job = Job() + val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndThrow(100, exception) } + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) + nativeSuspend({ _, _ -> + receivedResultCount.incrementAndGet() + }, { error, _ -> + assertNotNull(error, "Function should complete with an error") + val kotlinException = error.kotlinCause + assertSame(exception, kotlinException, "Kotlin exception should be the same exception") + receivedErrorCount.incrementAndGet() + }) + job.children.forEach { it.join() } // Waits for the function to complete + assertEquals(1, receivedErrorCount.value, "Error callback should be called once") + assertEquals(0, receivedResultCount.value, "Result callback shouldn't be called") + } + + @Test + fun ensure_function_is_cancelled() = runBlocking { + val job = Job() + val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(5_000, RandomValue()) } + val receivedResultCount = atomic(0) + val receivedErrorCount = atomic(0) + val cancel = nativeSuspend({ _, _ -> + receivedResultCount.incrementAndGet() + }, { error, _ -> + assertNotNull(error, "Function should complete with an error") + val exception = error.kotlinCause + assertIs(exception, "Error should contain CancellationException") + receivedErrorCount.incrementAndGet() + }) + delay(100) // Gives the function some time to start + cancel() + job.children.forEach { it.join() } // Waits for the function to complete + assertEquals(1, receivedErrorCount.value, "Error callback should be called once") + assertEquals(0, receivedResultCount.value, "Result callback shouldn't be called") + } +} \ No newline at end of file From 7a2510eb992772459faa34bb2b7857fdcb5ffc1a Mon Sep 17 00:00:00 2001 From: Ankush Gupta Date: Wed, 16 Feb 2022 21:53:23 -0800 Subject: [PATCH 10/10] wip: migrate supportedTargetTests to use runTest instead of runBlocking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this compiles, but doesn't pass on Kotlin/Native 😔 --- .../rickclephas/kmp/nativecoroutines/NativeFlowTests.kt | 9 +++++---- .../kmp/nativecoroutines/NativeSuspendTests.kt | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt index cd20c3fb..caaf0c01 100644 --- a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeFlowTests.kt @@ -4,11 +4,12 @@ import kotlinx.atomicfu.atomic import kotlinx.coroutines.* import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.test.runTest import kotlin.test.* class NativeFlowTests { @Test - fun ensure_completion_callback_is_invoked() = runBlocking { + fun ensure_completion_callback_is_invoked() = runTest { val flow = flow { } val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) @@ -22,7 +23,7 @@ class NativeFlowTests { } @Test - fun ensure_exceptions_are_received_as_errors() = runBlocking { + fun ensure_exceptions_are_received_as_errors() = runTest { val exception = RandomException() val flow = flow { throw exception } val job = Job() @@ -39,7 +40,7 @@ class NativeFlowTests { } @Test - fun ensure_values_are_received() = runBlocking { + fun ensure_values_are_received() = runTest { val values = listOf(RandomValue(), RandomValue(), RandomValue(), RandomValue()) val flow = flow { values.forEach { emit(it) } } val job = Job() @@ -54,7 +55,7 @@ class NativeFlowTests { } @Test - fun ensure_collection_is_cancelled() = runBlocking { + fun ensure_collection_is_cancelled() = runTest { val flow = MutableSharedFlow() val job = Job() val nativeFlow = flow.asNativeFlow(CoroutineScope(job)) diff --git a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt index ee4a7e91..b2a414f2 100644 --- a/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt +++ b/kmp-nativecoroutines-core/src/supportedTargetTest/kotlin/com/rickclephas/kmp/nativecoroutines/NativeSuspendTests.kt @@ -3,10 +3,10 @@ package com.rickclephas.kmp.nativecoroutines import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking import kotlin.coroutines.cancellation.CancellationException import kotlin.test.* import kotlinx.atomicfu.atomic +import kotlinx.coroutines.test.runTest class NativeSuspendTests { @@ -21,7 +21,7 @@ class NativeSuspendTests { } @Test - fun ensure_correct_result_is_received() = runBlocking { + fun ensure_correct_result_is_received() = runTest { val value = RandomValue() val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(100, value) } @@ -39,7 +39,7 @@ class NativeSuspendTests { } @Test - fun ensure_exceptions_are_received_as_errors() = runBlocking { + fun ensure_exceptions_are_received_as_errors() = runTest { val exception = RandomException() val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndThrow(100, exception) } @@ -59,7 +59,7 @@ class NativeSuspendTests { } @Test - fun ensure_function_is_cancelled() = runBlocking { + fun ensure_function_is_cancelled() = runTest { val job = Job() val nativeSuspend = nativeSuspend(CoroutineScope(job)) { delayAndReturn(5_000, RandomValue()) } val receivedResultCount = atomic(0)