blob: be51272dddcddf50d3ea5d4dcf4b276f93250324 [file] [log] [blame]
Roman Elizarova7db8ec2017-12-21 22:45:12 +03001/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03002 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarova7db8ec2017-12-21 22:45:12 +03003 */
4
Roman Elizarovc0d71dc2017-12-21 22:12:43 +03005package kotlinx.coroutines.experimental
6
Roman Elizarovaa461cf2018-04-11 13:20:29 +03007import kotlinx.coroutines.experimental.selects.*
8import kotlinx.coroutines.experimental.sync.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +03009import kotlin.coroutines.experimental.*
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030010import kotlin.test.*
11
Roman Elizarovaa461cf2018-04-11 13:20:29 +030012class AtomicCancellationCommonTest : TestBase() {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030013 @Test
Roman Elizarov1097bc82017-12-26 14:11:42 +030014 fun testCancellableLaunch() = runTest {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030015 expect(1)
16 val job = launch(coroutineContext) {
17 expectUnreached() // will get cancelled before start
18 }
19 expect(2)
20 job.cancel()
21 finish(3)
22 }
23
24 @Test
Roman Elizarov1097bc82017-12-26 14:11:42 +030025 fun testAtomicLaunch() = runTest {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030026 expect(1)
27 val job = launch(coroutineContext, start = CoroutineStart.ATOMIC) {
28 finish(4) // will execute even after it was cancelled
29 }
30 expect(2)
31 job.cancel()
32 expect(3)
33 }
34
35 @Test
Roman Elizarov1097bc82017-12-26 14:11:42 +030036 fun testDeferredAwaitCancellable() = runTest {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030037 expect(1)
38 val deferred = async(coroutineContext) { // deferred, not yet complete
39 expect(4)
40 "OK"
41 }
42 assertEquals(false, deferred.isCompleted)
43 var job: Job? = null
44 launch(coroutineContext) { // will cancel job as soon as deferred completes
45 expect(5)
46 assertEquals(true, deferred.isCompleted)
47 job!!.cancel()
48 }
49 job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
50 expect(2)
51 try {
52 deferred.await() // suspends
53 expectUnreached() // will not execute -- cancelled while dispatched
54 } finally {
55 finish(7) // but will execute finally blocks
56 }
57 }
58 expect(3) // continues to execute when job suspends
59 yield() // to deferred & canceller
60 expect(6)
61 }
62
63 @Test
Roman Elizarov1097bc82017-12-26 14:11:42 +030064 fun testJobJoinCancellable() = runTest {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030065 expect(1)
66 val jobToJoin = launch(coroutineContext) { // not yet complete
67 expect(4)
68 }
69 assertEquals(false, jobToJoin.isCompleted)
70 var job: Job? = null
71 launch(coroutineContext) { // will cancel job as soon as jobToJoin completes
72 expect(5)
73 assertEquals(true, jobToJoin.isCompleted)
74 job!!.cancel()
75 }
76 job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
77 expect(2)
78 try {
79 jobToJoin.join() // suspends
80 expectUnreached() // will not execute -- cancelled while dispatched
81 } finally {
82 finish(7) // but will execute finally blocks
83 }
84 }
85 expect(3) // continues to execute when job suspends
86 yield() // to jobToJoin & canceller
87 expect(6)
88 }
Roman Elizarovaa461cf2018-04-11 13:20:29 +030089
90 @Test
91 fun testLockAtomicCancel() = runTest {
92 expect(1)
93 val mutex = Mutex(true) // locked mutex
94 val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
95 expect(2)
96 mutex.lock() // suspends
97 expect(4) // should execute despite cancellation
98 }
99 expect(3)
100 mutex.unlock() // unlock mutex first
101 job.cancel() // cancel the job next
102 yield() // now yield
103 finish(5)
104 }
105
106 @Test
107 fun testSelectLockAtomicCancel() = runTest {
108 expect(1)
109 val mutex = Mutex(true) // locked mutex
110 val job = launch(coroutineContext, start = CoroutineStart.UNDISPATCHED) {
111 expect(2)
112 val result = select<String> { // suspends
113 mutex.onLock {
114 expect(4)
115 "OK"
116 }
117 }
118 assertEquals("OK", result)
119 expect(5) // should execute despite cancellation
120 }
121 expect(3)
122 mutex.unlock() // unlock mutex first
123 job.cancel() // cancel the job next
124 yield() // now yield
125 finish(6)
126 }
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300127}