• 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     @Suppress("UNUSED_VARIABLE")
29     @Test
<lambda>null30     fun testSelectSendCancellable() = runBlocking {
31         expect(1)
32         val channel = Channel<Int>()
33         val job = launch(start = CoroutineStart.UNDISPATCHED) {
34             expect(2)
35             val result = select<String> { // suspends
36                 channel.onSend(42) {
37                     expect(4)
38                     "OK"
39                 }
40             }
41             expectUnreached() // should NOT execute because of cancellation
42         }
43         expect(3)
44         assertEquals(42, channel.receive()) // will schedule sender for further execution
45         job.cancel() // cancel the job next
46         yield() // now yield
47         finish(4)
48     }
49 
50     @Test
<lambda>null51     fun testReceiveCancellable() = runBlocking {
52         expect(1)
53         val channel = Channel<Int>()
54         val job = launch(start = CoroutineStart.UNDISPATCHED) {
55             expect(2)
56             assertEquals(42, channel.receive()) // suspends
57             expectUnreached() // should NOT execute because of cancellation
58         }
59         expect(3)
60         channel.send(42) // will schedule receiver for further execution
61         job.cancel() // cancel the job next
62         yield() // now yield
63         finish(4)
64     }
65 
66     @Test
<lambda>null67     fun testSelectReceiveCancellable() = runBlocking {
68         expect(1)
69         val channel = Channel<Int>()
70         val job = launch(start = CoroutineStart.UNDISPATCHED) {
71             expect(2)
72             val result = select<String> { // suspends
73                 channel.onReceive {
74                     assertEquals(42, it)
75                     expect(4)
76                     "OK"
77                 }
78             }
79             expectUnreached() // should NOT execute because of cancellation
80         }
81         expect(3)
82         channel.send(42) // will schedule receiver for further execution
83         job.cancel() // cancel the job next
84         yield() // now yield
85         finish(4)
86     }
87 
88     @Test
<lambda>null89     fun testSelectDeferredAwaitCancellable() = runBlocking {
90         expect(1)
91         val deferred = async { // deferred, not yet complete
92             expect(4)
93             "OK"
94         }
95         assertEquals(false, deferred.isCompleted)
96         var job: Job? = null
97         launch { // will cancel job as soon as deferred completes
98             expect(5)
99             assertEquals(true, deferred.isCompleted)
100             job!!.cancel()
101         }
102         job = launch(start = CoroutineStart.UNDISPATCHED) {
103             expect(2)
104             try {
105                 select<Unit> { // suspends
106                     deferred.onAwait { expectUnreached() }
107                 }
108                 expectUnreached() // will not execute -- cancelled while dispatched
109             } finally {
110                 finish(7) // but will execute finally blocks
111             }
112         }
113         expect(3) // continues to execute when the job suspends
114         yield() // to deferred & canceller
115         expect(6)
116     }
117 
118     @Test
<lambda>null119     fun testSelectJobJoinCancellable() = runBlocking {
120         expect(1)
121         val jobToJoin = launch { // not yet complete
122             expect(4)
123         }
124         assertEquals(false, jobToJoin.isCompleted)
125         var job: Job? = null
126         launch { // will cancel job as soon as jobToJoin completes
127             expect(5)
128             assertEquals(true, jobToJoin.isCompleted)
129             job!!.cancel()
130         }
131         job = launch(start = CoroutineStart.UNDISPATCHED) {
132             expect(2)
133             try {
134                 select<Unit> { // suspends
135                     jobToJoin.onJoin { expectUnreached() }
136                 }
137                 expectUnreached() // will not execute -- cancelled while dispatched
138             } finally {
139                 finish(7) // but will execute finally blocks
140             }
141         }
142         expect(3) // continues to execute when the job suspends
143         yield() // to jobToJoin & canceller
144         expect(6)
145     }
146 }
147