/* * Copyright 2016-2019 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 kotlin.test.* @Suppress("DEPRECATION", "DEPRECATION_ERROR") class TestRunBlockingTest { @Test fun delay_advancesTimeAutomatically() = runBlockingTest { assertRunsFast { delay(SLOW) } } @Test fun callingSuspendWithDelay_advancesAutomatically() = runBlockingTest { suspend fun withDelay(): Int { delay(SLOW) return 3 } assertRunsFast { assertEquals(3, withDelay()) } } @Test fun launch_advancesAutomatically() = runBlockingTest { val job = launch { delay(SLOW) } assertRunsFast { job.join() assertTrue(job.isCompleted) } } @Test fun async_advancesAutomatically() = runBlockingTest { val deferred = async { delay(SLOW) 3 } assertRunsFast { assertEquals(3, deferred.await()) } } @Test fun whenUsingTimeout_triggersWhenDelayed() { assertFailsWith { runBlockingTest { assertRunsFast { withTimeout(SLOW) { delay(SLOW) } } } } } @Test fun whenUsingTimeout_doesNotTriggerWhenFast() = runBlockingTest { assertRunsFast { withTimeout(SLOW) { delay(0) } } } @Test fun whenUsingTimeout_triggersWhenWaiting() { assertFailsWith { runBlockingTest { val uncompleted = CompletableDeferred() assertRunsFast { withTimeout(SLOW) { uncompleted.await() } } } } } @Test fun whenUsingTimeout_doesNotTriggerWhenComplete() = runBlockingTest { val completed = CompletableDeferred() assertRunsFast { completed.complete(Unit) withTimeout(SLOW) { completed.await() } } } @Test fun testDelayInAsync_withAwait() = runBlockingTest { assertRunsFast { val deferred = async { delay(SLOW) 3 } assertEquals(3, deferred.await()) } } @Test fun whenUsingTimeout_inAsync_triggersWhenDelayed() { assertFailsWith { runBlockingTest { val deferred = async { withTimeout(SLOW) { delay(SLOW) } } assertRunsFast { deferred.await() } } } } @Test fun whenUsingTimeout_inAsync_doesNotTriggerWhenNotDelayed() = runBlockingTest { val deferred = async { withTimeout(SLOW) { delay(0) } } assertRunsFast { deferred.await() } } @Test fun whenUsingTimeout_inLaunch_triggersWhenDelayed() { assertFailsWith { runBlockingTest { val job = launch { withTimeout(1) { delay(SLOW + 1) } } assertRunsFast { job.join() throw job.getCancellationException() } } } } @Test fun whenUsingTimeout_inLaunch_doesNotTriggerWhenNotDelayed() = runBlockingTest { val job = launch { withTimeout(SLOW) { delay(0) } } assertRunsFast { job.join() assertTrue(job.isCompleted) } } @Test fun throwingException_throws() { assertFailsWith { runBlockingTest { assertRunsFast { delay(SLOW) throw IllegalArgumentException("Test") } } } } @Test fun throwingException_inLaunch_throws() { assertFailsWith { runBlockingTest { val job = launch { delay(SLOW) throw IllegalArgumentException("Test") } assertRunsFast { job.join() throw job.getCancellationException().cause ?: AssertionError("expected exception") } } } } @Test fun throwingException__inAsync_throws() { assertFailsWith { runBlockingTest { val deferred: Deferred = async { delay(SLOW) throw IllegalArgumentException("Test") } assertRunsFast { deferred.await() } } } } @Test fun callingLaunchFunction_executesLaunchBlockImmediately() = runBlockingTest { assertRunsFast { var executed = false launch { delay(SLOW) executed = true } delay(SLOW) assertTrue(executed) } } @Test fun callingAsyncFunction_executesAsyncBlockImmediately() = runBlockingTest { assertRunsFast { var executed = false val deferred = async { delay(SLOW) executed = true } advanceTimeBy(SLOW) assertTrue(deferred.isCompleted) assertTrue(executed) } } @Test fun nestingBuilders_executesSecondLevelImmediately() = runBlockingTest { assertRunsFast { var levels = 0 launch { delay(SLOW) levels++ launch { delay(SLOW) levels++ } } advanceUntilIdle() assertEquals(2, levels) } } @Test fun testCancellationException() = runBlockingTest { var actual: CancellationException? = null val uncompleted = CompletableDeferred() val job = launch { actual = kotlin.runCatching { uncompleted.await() }.exceptionOrNull() as? CancellationException } assertNull(actual) job.cancel() assertNotNull(actual) } @Test fun testCancellationException_notThrown() = runBlockingTest { val uncompleted = CompletableDeferred() val job = launch { uncompleted.await() } job.cancel() job.join() } @Test fun whenACoroutineLeaks_errorIsThrown() { assertFailsWith { runBlockingTest { val uncompleted = CompletableDeferred() launch { uncompleted.await() } } } } @Test fun runBlockingTestBuilder_throwsOnBadDispatcher() { assertFailsWith { runBlockingTest(Dispatchers.Default) { } } } @Test fun runBlockingTestBuilder_throwsOnBadHandler() { assertFailsWith { runBlockingTest(CoroutineExceptionHandler { _, _ -> }) { } } } @Test fun pauseDispatcher_disablesAutoAdvance_forCurrent() = runBlockingTest { var mutable = 0 pauseDispatcher { launch { mutable++ } assertEquals(0, mutable) runCurrent() assertEquals(1, mutable) } } @Test fun pauseDispatcher_disablesAutoAdvance_forDelay() = runBlockingTest { var mutable = 0 pauseDispatcher { launch { mutable++ delay(SLOW) mutable++ } assertEquals(0, mutable) runCurrent() assertEquals(1, mutable) advanceTimeBy(SLOW) assertEquals(2, mutable) } } @Test fun pauseDispatcher_withDelay_resumesAfterPause() = runBlockingTest { var mutable = 0 assertRunsFast { pauseDispatcher { delay(1_000) mutable++ } } assertEquals(1, mutable) } @Test fun testWithTestContextThrowingAnAssertionError() { assertFailsWith { runBlockingTest { val expectedError = TestException("hello") launch { throw expectedError } // don't rethrow or handle the exception } } } @Test fun testExceptionHandlingWithLaunch() { assertFailsWith { runBlockingTest { val expectedError = TestException("hello") launch { throw expectedError } } } } @Test fun testExceptions_notThrownImmediately() { assertFailsWith { runBlockingTest { val expectedException = TestException("hello") val result = runCatching { launch { throw expectedException } } runCurrent() assertEquals(true, result.isSuccess) } } } private val exceptionHandler = TestCoroutineExceptionHandler() @Test fun testPartialContextOverride() = runBlockingTest(CoroutineName("named")) { assertEquals(CoroutineName("named"), coroutineContext[CoroutineName]) assertNotNull(coroutineContext[CoroutineExceptionHandler]) assertNotSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler) } @Test fun testPartialDispatcherOverride() { assertFailsWith { runBlockingTest(Dispatchers.Unconfined) { fail("Unreached") } } } @Test fun testOverrideExceptionHandler() = runBlockingTest(exceptionHandler) { assertSame(coroutineContext[CoroutineExceptionHandler], exceptionHandler) } @Test fun testOverrideExceptionHandlerError() { assertFailsWith { runBlockingTest(CoroutineExceptionHandler { _, _ -> }) { fail("Unreached") } } } }