1 package kotlinx.coroutines 2 3 import kotlinx.coroutines.testing.* 4 import kotlin.coroutines.* 5 import kotlin.test.* 6 7 class CancellableContinuationJvmTest : TestBase() { 8 @Test <lambda>null9 fun testToString() = runTest { 10 checkToString() 11 } 12 checkToStringnull13 private suspend fun checkToString() { 14 suspendCancellableCoroutine<Unit> { 15 it.resume(Unit) 16 assertTrue(it.toString().contains("kotlinx.coroutines.CancellableContinuationJvmTest.checkToString(CancellableContinuationJvmTest.kt")) 17 } 18 suspend {}() // Eliminate tail-call optimization 19 } 20 21 @Test <lambda>null22 fun testExceptionIsNotReported() = runTest({ it is CancellationException }) { 23 val ctx = coroutineContext <lambda>null24 suspendCancellableCoroutine<Unit> { 25 ctx.cancel() 26 it.resumeWith(Result.failure(TestException())) 27 } 28 } 29 30 @Test <lambda>null31 fun testBlockingIntegration() = runTest { 32 val source = BlockingSource() 33 val job = launch(Dispatchers.Default) { 34 source.await() 35 } 36 source.cancelAndJoin(job) 37 } 38 39 @Test <lambda>null40 fun testBlockingIntegrationAlreadyCancelled() = runTest { 41 val source = BlockingSource() 42 val job = launch(Dispatchers.Default) { 43 cancel() 44 source.await() 45 } 46 source.cancelAndJoin(job) 47 } 48 cancelAndJoinnull49 private suspend fun BlockingSource.cancelAndJoin(job: Job) { 50 while (!hasSubscriber) { 51 Thread.sleep(10) 52 } 53 job.cancelAndJoin() 54 } 55 <lambda>null56 private suspend fun BlockingSource.await() = suspendCancellableCoroutine<Unit> { 57 it.invokeOnCancellation { this.cancel() } 58 subscribe() 59 } 60 61 private class BlockingSource { 62 @Volatile 63 private var isCancelled = false 64 65 @Volatile 66 public var hasSubscriber = false 67 subscribenull68 public fun subscribe() { 69 hasSubscriber = true 70 while (!isCancelled) { 71 Thread.sleep(10) 72 } 73 } 74 cancelnull75 public fun cancel() { 76 isCancelled = true 77 } 78 } 79 } 80