From edb10022259500057590306c1bc8dde1c1281c5e Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 16 Jul 2021 15:50:58 +0300 Subject: [PATCH 1/2] Introduce TestResult into TestBase as the first preparation step to multiplatform tests * The goal of this change is to test our IDE and tooling tolerance to hack-ish TestResult --- .../common/test/TestBase.common.kt | 9 ++++++++- .../test/flow/operators/FlatMapMergeBaseTest.kt | 2 +- kotlinx-coroutines-core/js/test/PromiseTest.kt | 14 +++++++++++++- kotlinx-coroutines-core/js/test/TestBase.kt | 7 +++++-- kotlinx-coroutines-core/jvm/test/TestBase.kt | 5 ++++- kotlinx-coroutines-core/native/test/TestBase.kt | 5 ++++- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/kotlinx-coroutines-core/common/test/TestBase.common.kt b/kotlinx-coroutines-core/common/test/TestBase.common.kt index 7ac696ddb8..71c45769cb 100644 --- a/kotlinx-coroutines-core/common/test/TestBase.common.kt +++ b/kotlinx-coroutines-core/common/test/TestBase.common.kt @@ -13,6 +13,13 @@ import kotlin.test.* public expect val isStressTest: Boolean public expect val stressTestMultiplier: Int +/** + * The result of a multiplatform asynchronous test. + * Aliases into Unit on K/JVM and K/N, and into Promise on K/JS. + */ +@Suppress("NO_ACTUAL_FOR_EXPECT") +public expect class TestResult + public expect open class TestBase constructor() { /* * In common tests we emulate parameterized tests @@ -33,7 +40,7 @@ public expect open class TestBase constructor() { expected: ((Throwable) -> Boolean)? = null, unhandled: List<(Throwable) -> Boolean> = emptyList(), block: suspend CoroutineScope.() -> Unit - ) + ): TestResult } public suspend inline fun hang(onCancellation: () -> Unit) { diff --git a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt index 44376980cd..4095172dab 100644 --- a/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt +++ b/kotlinx-coroutines-core/common/test/flow/operators/FlatMapMergeBaseTest.kt @@ -90,5 +90,5 @@ abstract class FlatMapMergeBaseTest : FlatMapBaseTest() { } @Test - abstract fun testFlatMapConcurrency() + abstract fun testFlatMapConcurrency(): TestResult } diff --git a/kotlinx-coroutines-core/js/test/PromiseTest.kt b/kotlinx-coroutines-core/js/test/PromiseTest.kt index d0f6b2b714..cc1297cd78 100644 --- a/kotlinx-coroutines-core/js/test/PromiseTest.kt +++ b/kotlinx-coroutines-core/js/test/PromiseTest.kt @@ -74,4 +74,16 @@ class PromiseTest : TestBase() { assertSame(d2, deferred) assertEquals("OK", d2.await()) } -} \ No newline at end of file + + @Test + fun testLeverageTestResult(): TestResult { + // Cannot use expect(..) here + var seq = 0 + val result = runTest { + ++seq + } + return result.then { + if (seq != 1) error("Unexpected result: $seq") + } + } +} diff --git a/kotlinx-coroutines-core/js/test/TestBase.kt b/kotlinx-coroutines-core/js/test/TestBase.kt index e3d0fdee2d..4c60d27ee9 100644 --- a/kotlinx-coroutines-core/js/test/TestBase.kt +++ b/kotlinx-coroutines-core/js/test/TestBase.kt @@ -9,6 +9,9 @@ import kotlin.js.* public actual val isStressTest: Boolean = false public actual val stressTestMultiplier: Int = 1 +@Suppress("ACTUAL_WITHOUT_EXPECT", "ACTUAL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE") +public actual typealias TestResult = Promise + public actual open class TestBase actual constructor() { public actual val isBoundByJsTestTimeout = true private var actionIndex = 0 @@ -18,7 +21,7 @@ public actual open class TestBase actual constructor() { /** * Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not - * complete successfully even if this exception is consumed somewhere in the test. + * complete successfully even if this exception is consumed so mewhere in the test. */ @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun error(message: Any, cause: Throwable? = null): Nothing { @@ -77,7 +80,7 @@ public actual open class TestBase actual constructor() { expected: ((Throwable) -> Boolean)? = null, unhandled: List<(Throwable) -> Boolean> = emptyList(), block: suspend CoroutineScope.() -> Unit - ): dynamic { + ): TestResult { var exCount = 0 var ex: Throwable? = null /* diff --git a/kotlinx-coroutines-core/jvm/test/TestBase.kt b/kotlinx-coroutines-core/jvm/test/TestBase.kt index f74321d72e..2192507d7d 100644 --- a/kotlinx-coroutines-core/jvm/test/TestBase.kt +++ b/kotlinx-coroutines-core/jvm/test/TestBase.kt @@ -30,6 +30,9 @@ public actual val stressTestMultiplier = stressTestMultiplierSqrt * stressTestMu public val stressTestMultiplierCbrt = cbrt(stressTestMultiplier.toDouble()).roundToInt() +@Suppress("ACTUAL_WITHOUT_EXPECT") +public actual typealias TestResult = Unit + /** * Base class for tests, so that tests for predictable scheduling of actions in multiple coroutines sharing a single * thread can be written. Use it like this: @@ -188,7 +191,7 @@ public actual open class TestBase actual constructor() { expected: ((Throwable) -> Boolean)? = null, unhandled: List<(Throwable) -> Boolean> = emptyList(), block: suspend CoroutineScope.() -> Unit - ) { + ): TestResult { var exCount = 0 var ex: Throwable? = null try { diff --git a/kotlinx-coroutines-core/native/test/TestBase.kt b/kotlinx-coroutines-core/native/test/TestBase.kt index d6d5ce519a..4ffa6c0b11 100644 --- a/kotlinx-coroutines-core/native/test/TestBase.kt +++ b/kotlinx-coroutines-core/native/test/TestBase.kt @@ -7,6 +7,9 @@ package kotlinx.coroutines public actual val isStressTest: Boolean = false public actual val stressTestMultiplier: Int = 1 +@Suppress("ACTUAL_WITHOUT_EXPECT") +public actual typealias TestResult = Unit + public actual open class TestBase actual constructor() { public actual val isBoundByJsTestTimeout = false private var actionIndex = 0 @@ -71,7 +74,7 @@ public actual open class TestBase actual constructor() { expected: ((Throwable) -> Boolean)? = null, unhandled: List<(Throwable) -> Boolean> = emptyList(), block: suspend CoroutineScope.() -> Unit - ) { + ): TestResult { var exCount = 0 var ex: Throwable? = null try { From 38cc2a2aed7d3ac1d9d8e876da256ba598f2ee1f Mon Sep 17 00:00:00 2001 From: Vsevolod Tolstopyatov Date: Fri, 16 Jul 2021 16:01:54 +0300 Subject: [PATCH 2/2] ~typo --- kotlinx-coroutines-core/js/test/TestBase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kotlinx-coroutines-core/js/test/TestBase.kt b/kotlinx-coroutines-core/js/test/TestBase.kt index 4c60d27ee9..5f84d92216 100644 --- a/kotlinx-coroutines-core/js/test/TestBase.kt +++ b/kotlinx-coroutines-core/js/test/TestBase.kt @@ -21,7 +21,7 @@ public actual open class TestBase actual constructor() { /** * Throws [IllegalStateException] like `error` in stdlib, but also ensures that the test will not - * complete successfully even if this exception is consumed so mewhere in the test. + * complete successfully even if this exception is consumed somewhere in the test. */ @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") public actual fun error(message: Any, cause: Throwable? = null): Nothing {