blob: d7ea3ac311c76b5749e70dab61f8fa1aebfcb59b [file] [log] [blame]
Roman Elizarove3f28842017-12-21 19:15:40 +03001/*
2 * Copyright 2016-2017 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
18
19package kotlinx.coroutines.experimental
20
Roman Elizarov9fe5f462018-02-21 19:05:52 +030021import kotlin.coroutines.experimental.*
Roman Elizarove3f28842017-12-21 19:15:40 +030022import kotlin.test.*
23
Roman Elizarovaa461cf2018-04-11 13:20:29 +030024class CompletableDeferredTest : TestBase() {
Roman Elizarove3f28842017-12-21 19:15:40 +030025 @Test
26 fun testFresh() {
27 val c = CompletableDeferred<String>()
28 checkFresh(c)
29 }
30
31 private fun checkFresh(c: CompletableDeferred<String>) {
32 assertEquals(true, c.isActive)
33 assertEquals(false, c.isCancelled)
34 assertEquals(false, c.isCompleted)
35 assertEquals(false, c.isCompletedExceptionally)
36 assertThrows<IllegalStateException> { c.getCancellationException() }
37 assertThrows<IllegalStateException> { c.getCompleted() }
38 assertThrows<IllegalStateException> { c.getCompletionExceptionOrNull() }
39 }
40
41 @Test
42 fun testComplete() {
43 val c = CompletableDeferred<String>()
44 assertEquals(true, c.complete("OK"))
45 checkCompleteOk(c)
46 assertEquals(false, c.complete("OK"))
47 checkCompleteOk(c)
48 }
49
50 private fun checkCompleteOk(c: CompletableDeferred<String>) {
51 assertEquals(false, c.isActive)
52 assertEquals(false, c.isCancelled)
53 assertEquals(true, c.isCompleted)
54 assertEquals(false, c.isCompletedExceptionally)
55 assertTrue(c.getCancellationException() is JobCancellationException)
56 assertEquals("OK", c.getCompleted())
57 assertEquals(null, c.getCompletionExceptionOrNull())
58 }
59
60 @Test
61 fun testCompleteWithException() {
62 val c = CompletableDeferred<String>()
63 assertEquals(true, c.completeExceptionally(TestException()))
64 checkCompleteTestException(c)
65 assertEquals(false, c.completeExceptionally(TestException()))
66 checkCompleteTestException(c)
67 }
68
69 private fun checkCompleteTestException(c: CompletableDeferred<String>) {
70 assertEquals(false, c.isActive)
71 assertEquals(false, c.isCancelled)
72 assertEquals(true, c.isCompleted)
73 assertEquals(true, c.isCompletedExceptionally)
74 assertTrue(c.getCancellationException() is JobCancellationException)
75 assertThrows<TestException> { c.getCompleted() }
76 assertTrue(c.getCompletionExceptionOrNull() is TestException)
77 }
78
79 @Test
80 fun testCancel() {
81 val c = CompletableDeferred<String>()
82 assertEquals(true, c.cancel())
83 checkCancel(c)
84 assertEquals(false, c.cancel())
85 checkCancel(c)
86 }
87
88 private fun checkCancel(c: CompletableDeferred<String>) {
89 assertEquals(false, c.isActive)
90 assertEquals(true, c.isCancelled)
91 assertEquals(true, c.isCompleted)
92 assertEquals(true, c.isCompletedExceptionally)
93 assertThrows<CancellationException> { c.getCompleted() }
94 assertTrue(c.getCompletionExceptionOrNull() is CancellationException)
95 }
96
97 @Test
98 fun testCancelWithException() {
99 val c = CompletableDeferred<String>()
100 assertEquals(true, c.cancel(TestException()))
101 checkCancelWithException(c)
102 assertEquals(false, c.cancel(TestException()))
103 checkCancelWithException(c)
104 }
105
106 private fun checkCancelWithException(c: CompletableDeferred<String>) {
107 assertEquals(false, c.isActive)
108 assertEquals(true, c.isCancelled)
109 assertEquals(true, c.isCompleted)
110 assertEquals(true, c.isCompletedExceptionally)
111 assertTrue(c.getCancellationException() is JobCancellationException)
112 assertThrows<TestException> { c.getCompleted() }
113 assertTrue(c.getCompletionExceptionOrNull() is TestException)
114 }
115
116 @Test
117 fun testParentCancelsChild() {
118 val parent = Job()
119 val c = CompletableDeferred<String>(parent)
120 checkFresh(c)
121 parent.cancel()
122 assertEquals(false, parent.isActive)
123 assertEquals(true, parent.isCancelled)
124 checkCancel(c)
125 }
126
127 @Test
128 fun testParentActiveOnChildCompletion() {
129 val parent = Job()
130 val c = CompletableDeferred<String>(parent)
131 checkFresh(c)
132 assertEquals(true, parent.isActive)
133 assertEquals(true, c.complete("OK"))
134 checkCompleteOk(c)
135 assertEquals(true, parent.isActive)
136 }
137
138 @Test
139 fun testParentActiveOnChildException() {
140 val parent = Job()
141 val c = CompletableDeferred<String>(parent)
142 checkFresh(c)
143 assertEquals(true, parent.isActive)
144 assertEquals(true, c.completeExceptionally(TestException()))
145 checkCompleteTestException(c)
146 assertEquals(true, parent.isActive)
147 }
148
149 @Test
150 fun testParentActiveOnChildCancellation() {
151 val parent = Job()
152 val c = CompletableDeferred<String>(parent)
153 checkFresh(c)
154 assertEquals(true, parent.isActive)
155 assertEquals(true, c.cancel())
156 checkCancel(c)
157 assertEquals(true, parent.isActive)
158 }
159
160 @Test
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300161 fun testAwait() = runTest {
Roman Elizarove3f28842017-12-21 19:15:40 +0300162 expect(1)
163 val c = CompletableDeferred<String>()
164 launch(coroutineContext, CoroutineStart.UNDISPATCHED) {
165 expect(2)
166 assertEquals("OK", c.await()) // suspends
167 expect(5)
168 assertEquals("OK", c.await()) // does not suspend
169 expect(6)
170 }
171 expect(3)
172 c.complete("OK")
173 expect(4)
174 yield() // to launch
175 finish(7)
176 }
177
Roman Elizarov4d626de2018-01-11 22:57:28 +0300178 @Test
179 fun testCancelAndAwaitParentWaitChildren() = runTest {
180 expect(1)
181 val parent = CompletableDeferred<String>()
182 launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) {
183 expect(2)
184 try {
185 yield() // will get cancelled
186 } finally {
187 expect(5)
188 }
189 }
190 expect(3)
191 parent.cancel()
192 expect(4)
193 try {
194 parent.await()
195 } catch (e: CancellationException) {
196 finish(6)
197 }
198 }
199
200 @Test
201 fun testCompleteAndAwaitParentWaitChildren() = runTest {
202 expect(1)
203 val parent = CompletableDeferred<String>()
204 launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) {
205 expect(2)
206 try {
207 yield() // will get cancelled
208 } finally {
209 expect(5)
210 }
211 }
212 expect(3)
213 parent.complete("OK")
214 expect(4)
215 assertEquals("OK", parent.await())
216 finish(6)
217 }
218
Roman Elizarove3f28842017-12-21 19:15:40 +0300219 private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) {
220 try {
221 block()
222 fail("Should not complete normally")
223 } catch (e: Throwable) {
224 assertTrue(e is T)
225 }
226 }
227
228 class TestException : Throwable()
229}