• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package kotlinx.coroutines
2 
3 import kotlinx.coroutines.testing.*
4 import kotlinx.coroutines.channels.*
5 import kotlinx.coroutines.selects.*
6 import kotlin.test.*
7 
8 class AtomicCancellationTest : TestBase() {
9     @Test
<lambda>null10     fun testSendCancellable() = runBlocking {
11         expect(1)
12         val channel = Channel<Int>()
13         val job = launch(start = CoroutineStart.UNDISPATCHED) {
14             expect(2)
15             channel.send(42) // suspends
16             expectUnreached() // should NOT execute because of cancellation
17         }
18         expect(3)
19         assertEquals(42, channel.receive()) // will schedule sender for further execution
20         job.cancel() // cancel the job next
21         yield() // now yield
22         finish(4)
23     }
24 
25     @Suppress("UNUSED_VARIABLE")
26     @Test
<lambda>null27     fun testSelectSendCancellable() = runBlocking {
28         expect(1)
29         val channel = Channel<Int>()
30         val job = launch(start = CoroutineStart.UNDISPATCHED) {
31             expect(2)
32             val result = select<String> { // suspends
33                 channel.onSend(42) {
34                     expect(4)
35                     "OK"
36                 }
37             }
38             expectUnreached() // should NOT execute because of cancellation
39         }
40         expect(3)
41         assertEquals(42, channel.receive()) // will schedule sender for further execution
42         job.cancel() // cancel the job next
43         yield() // now yield
44         finish(4)
45     }
46 
47     @Test
<lambda>null48     fun testReceiveCancellable() = runBlocking {
49         expect(1)
50         val channel = Channel<Int>()
51         val job = launch(start = CoroutineStart.UNDISPATCHED) {
52             expect(2)
53             assertEquals(42, channel.receive()) // suspends
54             expectUnreached() // should NOT execute because of cancellation
55         }
56         expect(3)
57         channel.send(42) // will schedule receiver for further execution
58         job.cancel() // cancel the job next
59         yield() // now yield
60         finish(4)
61     }
62 
63     @Test
<lambda>null64     fun testSelectReceiveCancellable() = runBlocking {
65         expect(1)
66         val channel = Channel<Int>()
67         val job = launch(start = CoroutineStart.UNDISPATCHED) {
68             expect(2)
69             val result = select<String> { // suspends
70                 channel.onReceive {
71                     assertEquals(42, it)
72                     expect(4)
73                     "OK"
74                 }
75             }
76             expectUnreached() // should NOT execute because of cancellation
77         }
78         expect(3)
79         channel.send(42) // will schedule receiver for further execution
80         job.cancel() // cancel the job next
81         yield() // now yield
82         finish(4)
83     }
84 
85     @Test
<lambda>null86     fun testSelectDeferredAwaitCancellable() = runBlocking {
87         expect(1)
88         val deferred = async { // deferred, not yet complete
89             expect(4)
90             "OK"
91         }
92         assertEquals(false, deferred.isCompleted)
93         var job: Job? = null
94         launch { // will cancel job as soon as deferred completes
95             expect(5)
96             assertEquals(true, deferred.isCompleted)
97             job!!.cancel()
98         }
99         job = launch(start = CoroutineStart.UNDISPATCHED) {
100             expect(2)
101             try {
102                 select<Unit> { // suspends
103                     deferred.onAwait { expectUnreached() }
104                 }
105                 expectUnreached() // will not execute -- cancelled while dispatched
106             } finally {
107                 finish(7) // but will execute finally blocks
108             }
109         }
110         expect(3) // continues to execute when the job suspends
111         yield() // to deferred & canceller
112         expect(6)
113     }
114 
115     @Test
<lambda>null116     fun testSelectJobJoinCancellable() = runBlocking {
117         expect(1)
118         val jobToJoin = launch { // not yet complete
119             expect(4)
120         }
121         assertEquals(false, jobToJoin.isCompleted)
122         var job: Job? = null
123         launch { // will cancel job as soon as jobToJoin completes
124             expect(5)
125             assertEquals(true, jobToJoin.isCompleted)
126             job!!.cancel()
127         }
128         job = launch(start = CoroutineStart.UNDISPATCHED) {
129             expect(2)
130             try {
131                 select<Unit> { // suspends
132                     jobToJoin.onJoin { expectUnreached() }
133                 }
134                 expectUnreached() // will not execute -- cancelled while dispatched
135             } finally {
136                 finish(7) // but will execute finally blocks
137             }
138         }
139         expect(3) // continues to execute when the job suspends
140         yield() // to jobToJoin & canceller
141         expect(6)
142     }
143 }
144