package kotlinx.coroutines import kotlinx.coroutines.testing.* import org.junit.* import org.junit.Test import java.util.concurrent.* import kotlin.test.* class JobChildStressTest : TestBase() { private val N_ITERATIONS = 10_000 * stressTestMultiplier private val pool = newFixedThreadPoolContext(3, "JobChildStressTest") @After fun tearDown() { pool.close() } /** * Perform concurrent launch of a child job & cancellation of the explicit parent job */ @Test @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") fun testChild() = runTest { val barrier = CyclicBarrier(3) repeat(N_ITERATIONS) { var wasLaunched = false var unhandledException: Throwable? = null val handler = CoroutineExceptionHandler { _, ex -> unhandledException = ex } val scope = CoroutineScope(pool + handler) val parent = CompletableDeferred() // concurrent child launcher val launcher = scope.launch { barrier.await() // A: launch child for a parent job launch(parent) { wasLaunched = true throw TestException() } } // concurrent cancel val canceller = scope.launch { barrier.await() // B: cancel parent job of a child parent.cancel() } barrier.await() joinAll(launcher, canceller, parent) assertNull(unhandledException) if (wasLaunched) { val exception = parent.getCompletionExceptionOrNull() assertIs(exception, "exception=$exception") } } } }