• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }