1 /* 2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.coroutines 6 7 import kotlin.coroutines.* 8 import kotlin.test.* 9 10 class CancellableContinuationJvmTest : TestBase() { 11 @Test <lambda>null12 fun testToString() = runTest { 13 checkToString() 14 } 15 checkToStringnull16 private suspend fun checkToString() { 17 suspendCancellableCoroutine<Unit> { 18 it.resume(Unit) 19 assertTrue(it.toString().contains("kotlinx.coroutines.CancellableContinuationJvmTest.checkToString(CancellableContinuationJvmTest.kt")) 20 } 21 suspend {}() // Eliminate tail-call optimization 22 } 23 24 @Test <lambda>null25 fun testExceptionIsNotReported() = runTest({ it is CancellationException }) { 26 val ctx = coroutineContext <lambda>null27 suspendCancellableCoroutine<Unit> { 28 ctx.cancel() 29 it.resumeWith(Result.failure(TestException())) 30 } 31 } 32 33 @Test <lambda>null34 fun testBlockingIntegration() = runTest { 35 val source = BlockingSource() 36 val job = launch(Dispatchers.Default) { 37 source.await() 38 } 39 source.cancelAndJoin(job) 40 } 41 42 @Test <lambda>null43 fun testBlockingIntegrationAlreadyCancelled() = runTest { 44 val source = BlockingSource() 45 val job = launch(Dispatchers.Default) { 46 cancel() 47 source.await() 48 } 49 source.cancelAndJoin(job) 50 } 51 cancelAndJoinnull52 private suspend fun BlockingSource.cancelAndJoin(job: Job) { 53 while (!hasSubscriber) { 54 Thread.sleep(10) 55 } 56 job.cancelAndJoin() 57 } 58 <lambda>null59 private suspend fun BlockingSource.await() = suspendCancellableCoroutine<Unit> { 60 it.invokeOnCancellation { this.cancel() } 61 subscribe() 62 } 63 64 private class BlockingSource { 65 @Volatile 66 private var isCancelled = false 67 68 @Volatile 69 public var hasSubscriber = false 70 subscribenull71 public fun subscribe() { 72 hasSubscriber = true 73 while (!isCancelled) { 74 Thread.sleep(10) 75 } 76 } 77 cancelnull78 public fun cancel() { 79 isCancelled = true 80 } 81 } 82 } 83