• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package kotlinx.coroutines
2 
3 import kotlinx.coroutines.testing.*
4 import kotlinx.coroutines.selects.*
5 import kotlinx.coroutines.sync.*
6 import kotlin.test.*
7 
8 class AtomicCancellationCommonTest : TestBase() {
9     @Test
<lambda>null10     fun testCancellableLaunch() = runTest {
11         expect(1)
12         val job = launch {
13             expectUnreached() // will get cancelled before start
14         }
15         expect(2)
16         job.cancel()
17         finish(3)
18     }
19 
20     @Test
<lambda>null21     fun testAtomicLaunch() = runTest {
22         expect(1)
23         val job = launch(start = CoroutineStart.ATOMIC) {
24             finish(4) // will execute even after it was cancelled
25         }
26         expect(2)
27         job.cancel()
28         expect(3)
29     }
30 
31     @Test
<lambda>null32     fun testUndispatchedLaunch() = runTest {
33         expect(1)
34         assertFailsWith<CancellationException> {
35             withContext(Job()) {
36                 cancel()
37                 launch(start = CoroutineStart.UNDISPATCHED) {
38                     expect(2)
39                     yield()
40                     expectUnreached()
41                 }
42             }
43         }
44         finish(3)
45     }
46 
47     @Test
<lambda>null48     fun testUndispatchedLaunchWithUnconfinedContext() = runTest {
49         expect(1)
50         assertFailsWith<CancellationException> {
51             withContext(Dispatchers.Unconfined + Job()) {
52                 cancel()
53                 launch(start = CoroutineStart.UNDISPATCHED) {
54                     expect(2)
55                     yield()
56                     expectUnreached()
57                 }
58             }
59         }
60         finish(3)
61     }
62 
63     @Test
<lambda>null64     fun testDeferredAwaitCancellable() = runTest {
65         expect(1)
66         val deferred = async { // deferred, not yet complete
67             expect(4)
68             "OK"
69         }
70         assertEquals(false, deferred.isCompleted)
71         var job: Job? = null
72         launch { // will cancel job as soon as deferred completes
73             expect(5)
74             assertEquals(true, deferred.isCompleted)
75             job!!.cancel()
76         }
77         job = launch(start = CoroutineStart.UNDISPATCHED) {
78             expect(2)
79             try {
80                 deferred.await() // suspends
81                 expectUnreached() // will not execute -- cancelled while dispatched
82             } finally {
83                 finish(7) // but will execute finally blocks
84             }
85         }
86         expect(3) // continues to execute when the job suspends
87         yield() // to deferred & canceller
88         expect(6)
89     }
90 
91     @Test
testJobJoinCancellablenull92     fun testJobJoinCancellable() = runTest {
93         expect(1)
94         val jobToJoin = launch { // not yet complete
95             expect(4)
96         }
97         assertEquals(false, jobToJoin.isCompleted)
98         var job: Job? = null
99         launch { // will cancel job as soon as jobToJoin completes
100             expect(5)
101             assertEquals(true, jobToJoin.isCompleted)
102             job!!.cancel()
103         }
104         job = launch(start = CoroutineStart.UNDISPATCHED) {
105             expect(2)
106             try {
107                 jobToJoin.join() // suspends
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 jobToJoin & canceller
115         expect(6)
116     }
117 
118     @Test
<lambda>null119     fun testLockCancellable() = runTest {
120         expect(1)
121         val mutex = Mutex(true) // locked mutex
122         val job = launch(start = CoroutineStart.UNDISPATCHED) {
123             expect(2)
124             mutex.lock() // suspends
125             expectUnreached() // should NOT execute because of cancellation
126         }
127         expect(3)
128         mutex.unlock() // unlock mutex first
129         job.cancel() // cancel the job next
130         yield() // now yield
131         finish(4)
132     }
133 
134     @Test
<lambda>null135     fun testSelectLockCancellable() = runTest {
136         expect(1)
137         val mutex = Mutex(true) // locked mutex
138         val job = launch(start = CoroutineStart.UNDISPATCHED) {
139             expect(2)
140             select<String> { // suspends
141                 mutex.onLock {
142                     expect(4)
143                     "OK"
144                 }
145             }
146             expectUnreached() // should NOT execute because of cancellation
147         }
148         expect(3)
149         mutex.unlock() // unlock mutex first
150         job.cancel() // cancel the job next
151         yield() // now yield
152         finish(4)
153     }
154 }
155