1 /* 2 * Copyright 2016-2020 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 /** 11 * When using [suspendCoroutine] from the standard library the continuation must be dispatched atomically, 12 * without checking for cancellation at any point in time. 13 */ 14 class DispatchedContinuationTest : TestBase() { 15 private lateinit var cont: Continuation<String> 16 17 @Test testCancelThenResumenull18 fun testCancelThenResume() = runTest { 19 expect(1) 20 launch(start = CoroutineStart.UNDISPATCHED) { 21 expect(2) 22 coroutineContext[Job]!!.cancel() 23 // a regular suspendCoroutine will still suspend despite the fact that coroutine was cancelled 24 val value = suspendCoroutine<String> { 25 expect(3) 26 cont = it 27 } 28 expect(6) 29 assertEquals("OK", value) 30 } 31 expect(4) 32 cont.resume("OK") 33 expect(5) 34 yield() // to the launched job 35 finish(7) 36 } 37 38 @Test <lambda>null39 fun testCancelThenResumeUnconfined() = runTest { 40 expect(1) 41 launch(Dispatchers.Unconfined) { 42 expect(2) 43 coroutineContext[Job]!!.cancel() 44 // a regular suspendCoroutine will still suspend despite the fact that coroutine was cancelled 45 val value = suspendCoroutine<String> { 46 expect(3) 47 cont = it 48 } 49 expect(5) 50 assertEquals("OK", value) 51 } 52 expect(4) 53 cont.resume("OK") // immediately resumes -- because unconfined 54 finish(6) 55 } 56 57 @Test <lambda>null58 fun testResumeThenCancel() = runTest { 59 expect(1) 60 val job = launch(start = CoroutineStart.UNDISPATCHED) { 61 expect(2) 62 val value = suspendCoroutine<String> { 63 expect(3) 64 cont = it 65 } 66 expect(7) 67 assertEquals("OK", value) 68 } 69 expect(4) 70 cont.resume("OK") 71 expect(5) 72 // now cancel the job, which the coroutine is waiting to be dispatched 73 job.cancel() 74 expect(6) 75 yield() // to the launched job 76 finish(8) 77 } 78 }