diff --git a/kotlinx-coroutines-test/common/src/DelayController.kt b/kotlinx-coroutines-test/common/src/DelayController.kt index 5d8686da6b..fd210631f3 100644 --- a/kotlinx-coroutines-test/common/src/DelayController.kt +++ b/kotlinx-coroutines-test/common/src/DelayController.kt @@ -1,6 +1,7 @@ /* * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +@file:Suppress("DEPRECATION") package kotlinx.coroutines.test @@ -100,7 +101,10 @@ public interface DelayController { * This is useful when testing functions that start a coroutine. By pausing the dispatcher assertions or * setup may be done between the time the coroutine is created and started. */ - @ExperimentalCoroutinesApi + @Deprecated( + "Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.", + level = DeprecationLevel.WARNING + ) public suspend fun pauseDispatcher(block: suspend () -> Unit) /** @@ -109,7 +113,10 @@ public interface DelayController { * When paused, the dispatcher will not execute any coroutines automatically, and you must call [runCurrent] or * [advanceTimeBy], or [advanceUntilIdle] to execute coroutines. */ - @ExperimentalCoroutinesApi + @Deprecated( + "Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.", + level = DeprecationLevel.WARNING + ) public fun pauseDispatcher() /** @@ -119,12 +126,15 @@ public interface DelayController { * time and execute coroutines scheduled in the future use, one of [advanceTimeBy], * or [advanceUntilIdle]. */ - @ExperimentalCoroutinesApi + @Deprecated( + "Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.", + level = DeprecationLevel.WARNING + ) public fun resumeDispatcher() } internal interface SchedulerAsDelayController: DelayController { - public val scheduler: TestCoroutineScheduler + val scheduler: TestCoroutineScheduler /** @suppress */ @Deprecated("This property delegates to the test scheduler, which may cause confusing behavior unless made explicit.", @@ -167,7 +177,7 @@ internal interface SchedulerAsDelayController: DelayController { scheduler.runCurrent() if (!scheduler.isIdle()) { throw UncompletedCoroutinesError( - "Unfinished coroutines during teardown. Ensure all coroutines are" + + "Unfinished coroutines during tear-down. Ensure all coroutines are" + " completed or cancelled by your test." ) } diff --git a/kotlinx-coroutines-test/common/src/TestCoroutineDispatcher.kt b/kotlinx-coroutines-test/common/src/TestCoroutineDispatcher.kt index 3537910ac5..32fe1829d3 100644 --- a/kotlinx-coroutines-test/common/src/TestCoroutineDispatcher.kt +++ b/kotlinx-coroutines-test/common/src/TestCoroutineDispatcher.kt @@ -21,7 +21,9 @@ import kotlin.coroutines.* * * @see DelayController */ -@ExperimentalCoroutinesApi +@Deprecated("The execution order of `TestCoroutineDispatcher` can be confusing, and the mechanism of " + + "pausing is typically misunderstood. Please use `StandardTestDispatcher` or `UnconfinedTestDispatcher` instead.", + level = DeprecationLevel.WARNING) public class TestCoroutineDispatcher(public override val scheduler: TestCoroutineScheduler = TestCoroutineScheduler()): TestDispatcher(), Delay, SchedulerAsDelayController { diff --git a/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt b/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt index c6025cdb45..7f3faf0211 100644 --- a/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt +++ b/kotlinx-coroutines-test/common/src/TestCoroutineDispatchers.kt @@ -86,8 +86,7 @@ public class UnconfinedTestDispatcher( * * One can additionally pass a [name] in order to more easily distinguish this dispatcher during debugging. * - * @see UnconfinedTestDispatcher for a dispatcher that immediately enters [launch] and [async] blocks and is not - * confined to any particular thread. + * @see UnconfinedTestDispatcher for a dispatcher that is not confined to any particular thread. */ @ExperimentalCoroutinesApi public class StandardTestDispatcher( diff --git a/kotlinx-coroutines-test/common/src/TestCoroutineScope.kt b/kotlinx-coroutines-test/common/src/TestCoroutineScope.kt index fcd591abd7..aa2756ceaf 100644 --- a/kotlinx-coroutines-test/common/src/TestCoroutineScope.kt +++ b/kotlinx-coroutines-test/common/src/TestCoroutineScope.kt @@ -46,12 +46,13 @@ private class TestCoroutineScopeImpl( override fun cleanupTestCoroutines() { try { - coroutineContext.uncaughtExceptionCaptor.cleanupTestCoroutinesCaptor() val delayController = coroutineContext.delayController if (delayController != null) { delayController.cleanupTestCoroutines() + coroutineContext.uncaughtExceptionCaptor.cleanupTestCoroutinesCaptor() } else { testScheduler.runCurrent() + coroutineContext.uncaughtExceptionCaptor.cleanupTestCoroutinesCaptor() if (!testScheduler.isIdle()) { throw UncompletedCoroutinesError( "Unfinished coroutines during teardown. Ensure all coroutines are" + diff --git a/kotlinx-coroutines-test/common/test/Helpers.kt b/kotlinx-coroutines-test/common/test/Helpers.kt index 8be3ea106a..68d9b6ee65 100644 --- a/kotlinx-coroutines-test/common/test/Helpers.kt +++ b/kotlinx-coroutines-test/common/test/Helpers.kt @@ -4,6 +4,7 @@ package kotlinx.coroutines.test +import kotlinx.atomicfu.* import kotlin.test.* import kotlin.time.* @@ -35,3 +36,32 @@ inline fun assertRunsFast(block: () -> T): T = assertRunsFast(Duration.secon expect fun testResultMap(block: (() -> Unit) -> Unit, test: () -> TestResult): TestResult class TestException(message: String? = null): Exception(message) + +/** + * A class inheriting from which allows to check the execution order inside tests. + * + * @see TestBase + */ +open class OrderedExecutionTestBase { + private val actionIndex = atomic(0) + private val finished = atomic(false) + + /** Expect the next action to be [index] in order. */ + protected fun expect(index: Int) { + val wasIndex = actionIndex.incrementAndGet() + check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" } + } + + /** Expect this action to be final, with the given [index]. */ + protected fun finish(index: Int) { + expect(index) + check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" } + } + + @AfterTest + fun ensureFinishCalls() { + assertTrue(finished.value || actionIndex.value == 0, "Expected `finish` to be called") + } +} + +internal fun T.void() { } diff --git a/kotlinx-coroutines-test/common/test/RunTestTest.kt b/kotlinx-coroutines-test/common/test/RunTestTest.kt index 38d4c61767..08a7714bec 100644 --- a/kotlinx-coroutines-test/common/test/RunTestTest.kt +++ b/kotlinx-coroutines-test/common/test/RunTestTest.kt @@ -57,7 +57,7 @@ class RunTestTest { delay(2000) } val deferred = async { - val job = launch(TestCoroutineDispatcher(testScheduler)) { + val job = launch(StandardTestDispatcher(testScheduler)) { launch { delay(500) } diff --git a/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt b/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt new file mode 100644 index 0000000000..7e8a6ad158 --- /dev/null +++ b/kotlinx-coroutines-test/common/test/StandardTestDispatcherTest.kt @@ -0,0 +1,57 @@ +/* + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + */ + +package kotlinx.coroutines.test + +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import kotlin.test.* + +class StandardTestDispatcherTest: OrderedExecutionTestBase() { + + private val scope = createTestCoroutineScope(StandardTestDispatcher()) + + @AfterTest + fun cleanup() = scope.cleanupTestCoroutines() + + /** Tests that the [StandardTestDispatcher] follows an execution order similar to `runBlocking`. */ + @Test + fun testFlowsNotSkippingValues() = scope.launch { + // https://github.com/Kotlin/kotlinx.coroutines/issues/1626#issuecomment-554632852 + val list = flowOf(1).onStart { emit(0) } + .combine(flowOf("A")) { int, str -> "$str$int" } + .toList() + assertEquals(list, listOf("A0", "A1")) + }.void() + + /** Tests that each [launch] gets dispatched. */ + @Test + fun testLaunchDispatched() = scope.launch { + expect(1) + launch { + expect(3) + } + finish(2) + }.void() + + /** Tests that dispatching is done in a predictable order and [yield] puts this task at the end of the queue. */ + @Test + fun testYield() = scope.launch { + expect(1) + scope.launch { + expect(3) + yield() + expect(6) + } + scope.launch { + expect(4) + yield() + finish(7) + } + expect(2) + yield() + expect(5) + }.void() + +} \ No newline at end of file diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt index faf9399483..4917541bde 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt +++ b/kotlinx-coroutines-test/common/test/TestCoroutineSchedulerTest.kt @@ -12,7 +12,7 @@ class TestCoroutineSchedulerTest { @Test fun testContextElement() = runTest { assertFailsWith { - withContext(TestCoroutineDispatcher()) { + withContext(StandardTestDispatcher()) { } } } @@ -44,28 +44,35 @@ class TestCoroutineSchedulerTest { /** Tests that if [TestCoroutineScheduler.advanceTimeBy] encounters an arithmetic overflow, all the tasks scheduled * until the moment [Long.MAX_VALUE] get run. */ @Test - fun testAdvanceTimeByEnormousDelays() = runTest { - val initialDelay = 10L - delay(initialDelay) - assertEquals(initialDelay, currentTime) - var enteredInfinity = false - launch { - delay(Long.MAX_VALUE - 1) // delay(Long.MAX_VALUE) does nothing - assertEquals(Long.MAX_VALUE, currentTime) - enteredInfinity = true - } - var enteredNearInfinity = false - launch { - delay(Long.MAX_VALUE - initialDelay - 1) - assertEquals(Long.MAX_VALUE - 1, currentTime) - enteredNearInfinity = true + fun testAdvanceTimeByEnormousDelays() = forTestDispatchers { + assertRunsFast { + with (createTestCoroutineScope(it)) { + launch { + val initialDelay = 10L + delay(initialDelay) + assertEquals(initialDelay, currentTime) + var enteredInfinity = false + launch { + delay(Long.MAX_VALUE - 1) // delay(Long.MAX_VALUE) does nothing + assertEquals(Long.MAX_VALUE, currentTime) + enteredInfinity = true + } + var enteredNearInfinity = false + launch { + delay(Long.MAX_VALUE - initialDelay - 1) + assertEquals(Long.MAX_VALUE - 1, currentTime) + enteredNearInfinity = true + } + testScheduler.advanceTimeBy(Long.MAX_VALUE) + assertFalse(enteredInfinity) + assertTrue(enteredNearInfinity) + assertEquals(Long.MAX_VALUE, currentTime) + testScheduler.runCurrent() + assertTrue(enteredInfinity) + } + testScheduler.advanceUntilIdle() + } } - testScheduler.advanceTimeBy(Long.MAX_VALUE) - assertFalse(enteredInfinity) - assertTrue(enteredNearInfinity) - assertEquals(Long.MAX_VALUE, currentTime) - testScheduler.runCurrent() - assertTrue(enteredInfinity) } /** Tests the basic functionality of [TestCoroutineScheduler.advanceTimeBy]. */ @@ -124,48 +131,52 @@ class TestCoroutineSchedulerTest { /** Tests that [TestCoroutineScheduler.runCurrent] will not run new tasks after the current time has advanced. */ @Test - fun testRunCurrentNotDrainingQueue() = assertRunsFast { - val scheduler = TestCoroutineScheduler() - val scope = createTestCoroutineScope(scheduler) - var stage = 1 - scope.launch { - delay(SLOW) - launch { + fun testRunCurrentNotDrainingQueue() = forTestDispatchers { + assertRunsFast { + val scheduler = it.scheduler + val scope = createTestCoroutineScope(it) + var stage = 1 + scope.launch { delay(SLOW) - stage = 3 + launch { + delay(SLOW) + stage = 3 + } + scheduler.advanceTimeBy(SLOW) + stage = 2 } scheduler.advanceTimeBy(SLOW) - stage = 2 + assertEquals(1, stage) + scheduler.runCurrent() + assertEquals(2, stage) + scheduler.runCurrent() + assertEquals(3, stage) } - scheduler.advanceTimeBy(SLOW) - assertEquals(1, stage) - scheduler.runCurrent() - assertEquals(2, stage) - scheduler.runCurrent() - assertEquals(3, stage) } /** Tests that [TestCoroutineScheduler.advanceUntilIdle] doesn't hang when itself running in a scheduler task. */ @Test - fun testNestedAdvanceUntilIdle() = assertRunsFast { - val scheduler = TestCoroutineScheduler() - val scope = createTestCoroutineScope(scheduler) - var executed = false - scope.launch { - launch { - delay(SLOW) - executed = true + fun testNestedAdvanceUntilIdle() = forTestDispatchers { + assertRunsFast { + val scheduler = it.scheduler + val scope = createTestCoroutineScope(it) + var executed = false + scope.launch { + launch { + delay(SLOW) + executed = true + } + scheduler.advanceUntilIdle() } scheduler.advanceUntilIdle() + assertTrue(executed) } - scheduler.advanceUntilIdle() - assertTrue(executed) } /** Tests [yield] scheduling tasks for future execution and not executing immediately. */ @Test - fun testYield() { - val scope = createTestCoroutineScope() + fun testYield() = forTestDispatchers { + val scope = createTestCoroutineScope(it) var stage = 0 scope.launch { yield() @@ -182,6 +193,46 @@ class TestCoroutineSchedulerTest { scope.runCurrent() } + /** Tests that dispatching the delayed tasks is ordered by their waking times. */ + @Test + fun testDelaysPriority() = forTestDispatchers { + val scope = createTestCoroutineScope(it) + var lastMeasurement = 0L + fun checkTime(time: Long) { + assertTrue(lastMeasurement < time) + assertEquals(time, scope.currentTime) + lastMeasurement = scope.currentTime + } + scope.launch { + launch { + delay(100) + checkTime(100) + val deferred = async { + delay(70) + checkTime(170) + } + delay(1) + checkTime(101) + deferred.await() + delay(1) + checkTime(171) + } + launch { + delay(200) + checkTime(200) + } + launch { + delay(150) + checkTime(150) + delay(22) + checkTime(172) + } + delay(201) + } + scope.advanceUntilIdle() + checkTime(201) + } + private fun TestCoroutineScope.checkTimeout( timesOut: Boolean, timeoutMillis: Long = SLOW, block: suspend () -> Unit ) = assertRunsFast { @@ -205,8 +256,8 @@ class TestCoroutineSchedulerTest { /** Tests that timeouts get triggered. */ @Test - fun testSmallTimeouts() { - val scope = createTestCoroutineScope(TestCoroutineDispatcher()) + fun testSmallTimeouts() = forTestDispatchers { + val scope = createTestCoroutineScope(it) scope.checkTimeout(true) { val half = SLOW / 2 delay(half) @@ -216,8 +267,8 @@ class TestCoroutineSchedulerTest { /** Tests that timeouts don't get triggered if the code finishes in time. */ @Test - fun testLargeTimeouts() { - val scope = createTestCoroutineScope() + fun testLargeTimeouts() = forTestDispatchers { + val scope = createTestCoroutineScope(it) scope.checkTimeout(false) { val half = SLOW / 2 delay(half) @@ -227,8 +278,8 @@ class TestCoroutineSchedulerTest { /** Tests that timeouts get triggered if the code fails to finish in time asynchronously. */ @Test - fun testSmallAsynchronousTimeouts() { - val scope = createTestCoroutineScope() + fun testSmallAsynchronousTimeouts() = forTestDispatchers { + val scope = createTestCoroutineScope(it) val deferred = CompletableDeferred() scope.launch { val half = SLOW / 2 @@ -243,8 +294,8 @@ class TestCoroutineSchedulerTest { /** Tests that timeouts don't get triggered if the code finishes in time, even if it does so asynchronously. */ @Test - fun testLargeAsynchronousTimeouts() { - val scope = createTestCoroutineScope() + fun testLargeAsynchronousTimeouts() = forTestDispatchers { + val scope = createTestCoroutineScope(it) val deferred = CompletableDeferred() scope.launch { val half = SLOW / 2 @@ -256,4 +307,19 @@ class TestCoroutineSchedulerTest { deferred.await() } } + + private fun forTestDispatchers(block: (TestDispatcher) -> Unit): Unit = + @Suppress("DEPRECATION") + listOf( + TestCoroutineDispatcher(), + TestCoroutineDispatcher().also { it.pauseDispatcher() }, + StandardTestDispatcher(), + UnconfinedTestDispatcher() + ).forEach { + try { + block(it) + } catch (e: Throwable) { + throw RuntimeException("Test failed for dispatcher $it", e) + } + } } diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineScopeTest.kt b/kotlinx-coroutines-test/common/test/TestCoroutineScopeTest.kt index 9dbc63f8c9..01b0a28b7b 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineScopeTest.kt +++ b/kotlinx-coroutines-test/common/test/TestCoroutineScopeTest.kt @@ -29,7 +29,7 @@ class TestCoroutineScopeTest { } // Reuses the scheduler that the dispatcher is linked to. run { - val dispatcher = TestCoroutineDispatcher() + val dispatcher = StandardTestDispatcher() val scope = createTestCoroutineScope(dispatcher) assertSame(dispatcher.scheduler, scope.coroutineContext[TestCoroutineScheduler]) } @@ -43,7 +43,7 @@ class TestCoroutineScopeTest { // Doesn't touch the passed dispatcher and the scheduler if they match. run { val scheduler = TestCoroutineScheduler() - val dispatcher = TestCoroutineDispatcher(scheduler) + val dispatcher = StandardTestDispatcher(scheduler) val scope = createTestCoroutineScope(scheduler + dispatcher) assertSame(scheduler, scope.coroutineContext[TestCoroutineScheduler]) assertSame(dispatcher, scope.coroutineContext[ContinuationInterceptor]) @@ -123,7 +123,7 @@ class TestCoroutineScopeTest { /** Tests that uncaught exceptions are thrown at the cleanup. */ @Test fun testThrowsUncaughtExceptionsOnCleanup() { - val scope = TestCoroutineScope() + val scope = createTestCoroutineScope() val exception = TestException("test") scope.launch { throw exception @@ -136,7 +136,7 @@ class TestCoroutineScopeTest { /** Tests that uncaught exceptions take priority over uncompleted jobs when throwing on cleanup. */ @Test fun testUncaughtExceptionsPrioritizedOnCleanup() { - val scope = TestCoroutineScope() + val scope = createTestCoroutineScope() val exception = TestException("test") scope.launch { throw exception @@ -152,7 +152,7 @@ class TestCoroutineScopeTest { companion object { internal val invalidContexts = listOf( Dispatchers.Default, // not a [TestDispatcher] - TestCoroutineDispatcher() + TestCoroutineScheduler(), // the dispatcher is not linked to the scheduler + StandardTestDispatcher() + TestCoroutineScheduler(), // the dispatcher is not linked to the scheduler CoroutineExceptionHandler { _, _ -> }, // not an `UncaughtExceptionCaptor` ) } diff --git a/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt b/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt index 3ec110ebcf..0c3cac71ae 100644 --- a/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt +++ b/kotlinx-coroutines-test/common/test/TestDispatchersTest.kt @@ -3,24 +3,11 @@ */ package kotlinx.coroutines.test -import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlin.coroutines.* import kotlin.test.* -class TestDispatchersTest { - private val actionIndex = atomic(0) - private val finished = atomic(false) - - private fun expect(index: Int) { - val wasIndex = actionIndex.incrementAndGet() - check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" } - } - - private fun finish(index: Int) { - expect(index) - check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" } - } +class TestDispatchersTest: OrderedExecutionTestBase() { @BeforeTest fun setUp() { diff --git a/kotlinx-coroutines-test/common/test/TestBuildersTest.kt b/kotlinx-coroutines-test/common/test/migration/TestBuildersTest.kt similarity index 99% rename from kotlinx-coroutines-test/common/test/TestBuildersTest.kt rename to kotlinx-coroutines-test/common/test/migration/TestBuildersTest.kt index 7fefaf78b5..6d49a01fa4 100644 --- a/kotlinx-coroutines-test/common/test/TestBuildersTest.kt +++ b/kotlinx-coroutines-test/common/test/migration/TestBuildersTest.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.* import kotlin.coroutines.* import kotlin.test.* +@Suppress("DEPRECATION") class TestBuildersTest { @Test diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineDispatcherOrderTest.kt b/kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherOrderTest.kt similarity index 70% rename from kotlinx-coroutines-test/common/test/TestCoroutineDispatcherOrderTest.kt rename to kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherOrderTest.kt index e54ba21568..93fcd909cc 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineDispatcherOrderTest.kt +++ b/kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherOrderTest.kt @@ -8,20 +8,8 @@ import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlin.test.* -class TestCoroutineDispatcherOrderTest { - - private val actionIndex = atomic(0) - private val finished = atomic(false) - - private fun expect(index: Int) { - val wasIndex = actionIndex.incrementAndGet() - check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" } - } - - private fun finish(index: Int) { - expect(index) - check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" } - } +@Suppress("DEPRECATION") +class TestCoroutineDispatcherOrderTest: OrderedExecutionTestBase() { @Test fun testAdvanceTimeBy_progressesOnEachDelay() { diff --git a/kotlinx-coroutines-test/common/test/TestCoroutineDispatcherTest.kt b/kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherTest.kt similarity index 98% rename from kotlinx-coroutines-test/common/test/TestCoroutineDispatcherTest.kt rename to kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherTest.kt index f14b72632c..a78d923d34 100644 --- a/kotlinx-coroutines-test/common/test/TestCoroutineDispatcherTest.kt +++ b/kotlinx-coroutines-test/common/test/migration/TestCoroutineDispatcherTest.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* import kotlin.test.* +@Suppress("DEPRECATION") class TestCoroutineDispatcherTest { @Test fun whenDispatcherPaused_doesNotAutoProgressCurrent() { diff --git a/kotlinx-coroutines-test/common/test/TestRunBlockingOrderTest.kt b/kotlinx-coroutines-test/common/test/migration/TestRunBlockingOrderTest.kt similarity index 76% rename from kotlinx-coroutines-test/common/test/TestRunBlockingOrderTest.kt rename to kotlinx-coroutines-test/common/test/migration/TestRunBlockingOrderTest.kt index 5d94bd2866..32514d90e8 100644 --- a/kotlinx-coroutines-test/common/test/TestRunBlockingOrderTest.kt +++ b/kotlinx-coroutines-test/common/test/migration/TestRunBlockingOrderTest.kt @@ -4,24 +4,11 @@ package kotlinx.coroutines.test -import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlin.test.* -class TestRunBlockingOrderTest { - - private val actionIndex = atomic(0) - private val finished = atomic(false) - - private fun expect(index: Int) { - val wasIndex = actionIndex.incrementAndGet() - check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" } - } - - private fun finish(index: Int) { - expect(index) - check(!finished.getAndSet(true)) { "Should call 'finish(...)' at most once" } - } +@Suppress("DEPRECATION") +class TestRunBlockingOrderTest: OrderedExecutionTestBase() { @Test fun testLaunchImmediate() = runBlockingTest { @@ -90,4 +77,4 @@ class TestRunBlockingOrderTest { } finish(2) } -} +} \ No newline at end of file diff --git a/kotlinx-coroutines-test/common/test/TestRunBlockingTest.kt b/kotlinx-coroutines-test/common/test/migration/TestRunBlockingTest.kt similarity index 99% rename from kotlinx-coroutines-test/common/test/TestRunBlockingTest.kt rename to kotlinx-coroutines-test/common/test/migration/TestRunBlockingTest.kt index 139229e610..66c06cf49f 100644 --- a/kotlinx-coroutines-test/common/test/TestRunBlockingTest.kt +++ b/kotlinx-coroutines-test/common/test/migration/TestRunBlockingTest.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.test import kotlinx.coroutines.* import kotlin.test.* +@Suppress("DEPRECATION") class TestRunBlockingTest { @Test