blob: 28d85fe3416039eaf40d2a20d9768698fe4943f1 [file] [log] [blame]
/*
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
package kotlinx.coroutines.exceptions
import kotlinx.coroutines.*
import org.junit.Test
import java.io.*
import kotlin.test.*
/*
* Basic checks that check that cancellation more or less works,
* parent is not cancelled on child cancellation and launch {}, Job(), async {} and
* CompletableDeferred behave properly
*/
@Suppress("DEPRECATION") // cancel(cause)
class JobBasicCancellationTest : TestBase() {
@Test
fun testJobCancelChild() = runTest {
val parent = launch {
expect(1)
val child = launch {
expect(2)
}
yield()
expect(3)
child.cancel()
child.join()
expect(4)
}
parent.join()
finish(5)
}
@Test
fun testJobCancelChildAtomic() = runTest {
val parent = launch {
expect(1)
val child = launch(start = CoroutineStart.ATOMIC) {
expect(3)
}
expect(2)
child.cancel()
child.join()
yield()
expect(4)
}
parent.join()
assertTrue(parent.isCompleted)
assertFalse(parent.isCancelled)
finish(5)
}
@Test
fun testAsyncCancelChild() = runTest {
val parent = async {
expect(1)
val child = async {
expect(2)
}
yield()
expect(3)
child.cancel()
child.await()
expect(4)
}
parent.await()
finish(5)
}
@Test
fun testAsyncCancelChildAtomic() = runTest {
val parent = async {
expect(1)
val child = async(start = CoroutineStart.ATOMIC) {
expect(3)
}
expect(2)
child.cancel()
child.join()
expect(4)
}
parent.await()
finish(5)
}
@Test
fun testNestedAsyncFailure() = runTest {
val deferred = async(NonCancellable) {
val nested = async(NonCancellable) {
expect(3)
throw IOException()
}
expect(2)
yield()
expect(4)
nested.await()
}
expect(1)
try {
deferred.await()
} catch (e: IOException) {
finish(5)
}
}
@Test
fun testCancelJobImpl() = runTest {
val parent = launch {
expect(1)
val child = Job(coroutineContext[Job])
expect(2)
child.cancel() // cancel without cause -- should not cancel us (parent)
child.join()
expect(3)
}
parent.join()
finish(4)
}
@Test
fun cancelCompletableDeferred() = runTest {
val parent = launch {
expect(1)
val child = CompletableDeferred<Unit>(coroutineContext[Job])
expect(2)
child.cancel() // cancel without cause -- should not cancel us (parent)
child.join()
expect(3)
}
parent.join()
finish(4)
}
@Test
fun testConsecutiveCancellation() {
val deferred = CompletableDeferred<Int>()
assertTrue(deferred.completeExceptionally(IndexOutOfBoundsException()))
assertFalse(deferred.completeExceptionally(AssertionError())) // second is too late
val cause = deferred.getCancellationException().cause!!
assertTrue(cause is IndexOutOfBoundsException)
assertNull(cause.cause)
assertTrue(cause.suppressed.isEmpty())
}
}