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