blob: 59d440cd470b0da0f068b87ea47f7f70bde36236 [file] [log] [blame]
Roman Elizarove3f28842017-12-21 19:15:40 +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 Elizarove3f28842017-12-21 19:15:40 +03003 */
4
5@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
6
7package kotlinx.coroutines.experimental
8
Roman Elizarov9fe5f462018-02-21 19:05:52 +03009import kotlin.coroutines.experimental.*
Roman Elizarove3f28842017-12-21 19:15:40 +030010import kotlin.test.*
11
Roman Elizarovaa461cf2018-04-11 13:20:29 +030012class CompletableDeferredTest : TestBase() {
Roman Elizarove3f28842017-12-21 19:15:40 +030013 @Test
14 fun testFresh() {
15 val c = CompletableDeferred<String>()
16 checkFresh(c)
17 }
18
19 private fun checkFresh(c: CompletableDeferred<String>) {
20 assertEquals(true, c.isActive)
21 assertEquals(false, c.isCancelled)
22 assertEquals(false, c.isCompleted)
23 assertEquals(false, c.isCompletedExceptionally)
24 assertThrows<IllegalStateException> { c.getCancellationException() }
25 assertThrows<IllegalStateException> { c.getCompleted() }
26 assertThrows<IllegalStateException> { c.getCompletionExceptionOrNull() }
27 }
28
29 @Test
30 fun testComplete() {
31 val c = CompletableDeferred<String>()
32 assertEquals(true, c.complete("OK"))
33 checkCompleteOk(c)
34 assertEquals(false, c.complete("OK"))
35 checkCompleteOk(c)
36 }
37
38 private fun checkCompleteOk(c: CompletableDeferred<String>) {
39 assertEquals(false, c.isActive)
40 assertEquals(false, c.isCancelled)
41 assertEquals(true, c.isCompleted)
42 assertEquals(false, c.isCompletedExceptionally)
43 assertTrue(c.getCancellationException() is JobCancellationException)
44 assertEquals("OK", c.getCompleted())
45 assertEquals(null, c.getCompletionExceptionOrNull())
46 }
47
48 @Test
49 fun testCompleteWithException() {
50 val c = CompletableDeferred<String>()
51 assertEquals(true, c.completeExceptionally(TestException()))
52 checkCompleteTestException(c)
53 assertEquals(false, c.completeExceptionally(TestException()))
54 checkCompleteTestException(c)
55 }
56
57 private fun checkCompleteTestException(c: CompletableDeferred<String>) {
58 assertEquals(false, c.isActive)
59 assertEquals(false, c.isCancelled)
60 assertEquals(true, c.isCompleted)
61 assertEquals(true, c.isCompletedExceptionally)
62 assertTrue(c.getCancellationException() is JobCancellationException)
63 assertThrows<TestException> { c.getCompleted() }
64 assertTrue(c.getCompletionExceptionOrNull() is TestException)
65 }
66
67 @Test
68 fun testCancel() {
69 val c = CompletableDeferred<String>()
70 assertEquals(true, c.cancel())
71 checkCancel(c)
72 assertEquals(false, c.cancel())
73 checkCancel(c)
74 }
75
76 private fun checkCancel(c: CompletableDeferred<String>) {
77 assertEquals(false, c.isActive)
78 assertEquals(true, c.isCancelled)
79 assertEquals(true, c.isCompleted)
80 assertEquals(true, c.isCompletedExceptionally)
81 assertThrows<CancellationException> { c.getCompleted() }
82 assertTrue(c.getCompletionExceptionOrNull() is CancellationException)
83 }
84
85 @Test
86 fun testCancelWithException() {
87 val c = CompletableDeferred<String>()
88 assertEquals(true, c.cancel(TestException()))
89 checkCancelWithException(c)
90 assertEquals(false, c.cancel(TestException()))
91 checkCancelWithException(c)
92 }
93
94 private fun checkCancelWithException(c: CompletableDeferred<String>) {
95 assertEquals(false, c.isActive)
96 assertEquals(true, c.isCancelled)
97 assertEquals(true, c.isCompleted)
98 assertEquals(true, c.isCompletedExceptionally)
99 assertTrue(c.getCancellationException() is JobCancellationException)
100 assertThrows<TestException> { c.getCompleted() }
101 assertTrue(c.getCompletionExceptionOrNull() is TestException)
102 }
103
104 @Test
105 fun testParentCancelsChild() {
106 val parent = Job()
107 val c = CompletableDeferred<String>(parent)
108 checkFresh(c)
109 parent.cancel()
110 assertEquals(false, parent.isActive)
111 assertEquals(true, parent.isCancelled)
112 checkCancel(c)
113 }
114
115 @Test
116 fun testParentActiveOnChildCompletion() {
117 val parent = Job()
118 val c = CompletableDeferred<String>(parent)
119 checkFresh(c)
120 assertEquals(true, parent.isActive)
121 assertEquals(true, c.complete("OK"))
122 checkCompleteOk(c)
123 assertEquals(true, parent.isActive)
124 }
125
126 @Test
127 fun testParentActiveOnChildException() {
128 val parent = Job()
129 val c = CompletableDeferred<String>(parent)
130 checkFresh(c)
131 assertEquals(true, parent.isActive)
132 assertEquals(true, c.completeExceptionally(TestException()))
133 checkCompleteTestException(c)
134 assertEquals(true, parent.isActive)
135 }
136
137 @Test
138 fun testParentActiveOnChildCancellation() {
139 val parent = Job()
140 val c = CompletableDeferred<String>(parent)
141 checkFresh(c)
142 assertEquals(true, parent.isActive)
143 assertEquals(true, c.cancel())
144 checkCancel(c)
145 assertEquals(true, parent.isActive)
146 }
147
148 @Test
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300149 fun testAwait() = runTest {
Roman Elizarove3f28842017-12-21 19:15:40 +0300150 expect(1)
151 val c = CompletableDeferred<String>()
152 launch(coroutineContext, CoroutineStart.UNDISPATCHED) {
153 expect(2)
154 assertEquals("OK", c.await()) // suspends
155 expect(5)
156 assertEquals("OK", c.await()) // does not suspend
157 expect(6)
158 }
159 expect(3)
160 c.complete("OK")
161 expect(4)
162 yield() // to launch
163 finish(7)
164 }
165
Roman Elizarov4d626de2018-01-11 22:57:28 +0300166 @Test
167 fun testCancelAndAwaitParentWaitChildren() = runTest {
168 expect(1)
169 val parent = CompletableDeferred<String>()
170 launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) {
171 expect(2)
172 try {
173 yield() // will get cancelled
174 } finally {
175 expect(5)
176 }
177 }
178 expect(3)
179 parent.cancel()
180 expect(4)
181 try {
182 parent.await()
183 } catch (e: CancellationException) {
184 finish(6)
185 }
186 }
187
188 @Test
189 fun testCompleteAndAwaitParentWaitChildren() = runTest {
190 expect(1)
191 val parent = CompletableDeferred<String>()
192 launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) {
193 expect(2)
194 try {
195 yield() // will get cancelled
196 } finally {
197 expect(5)
198 }
199 }
200 expect(3)
201 parent.complete("OK")
202 expect(4)
203 assertEquals("OK", parent.await())
204 finish(6)
205 }
206
Roman Elizarove3f28842017-12-21 19:15:40 +0300207 private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) {
208 try {
209 block()
210 fail("Should not complete normally")
211 } catch (e: Throwable) {
212 assertTrue(e is T)
213 }
214 }
215
216 class TestException : Throwable()
217}