1 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913 2 3 package kotlinx.coroutines 4 5 import kotlinx.coroutines.testing.* 6 import kotlin.test.* 7 8 class CompletableDeferredTest : TestBase() { 9 @Test testFreshnull10 fun testFresh() { 11 val c = CompletableDeferred<String>() 12 checkFresh(c) 13 } 14 15 @Test testCompletenull16 fun testComplete() { 17 val c = CompletableDeferred<String>() 18 assertEquals(true, c.complete("OK")) 19 checkCompleteOk(c) 20 assertEquals("OK", c.getCompleted()) 21 assertEquals(false, c.complete("OK")) 22 checkCompleteOk(c) 23 assertEquals("OK", c.getCompleted()) 24 } 25 26 @Test testCompleteWithIncompleteResultnull27 fun testCompleteWithIncompleteResult() { 28 val c = CompletableDeferred<DisposableHandle>() 29 assertEquals(true, c.complete(c.invokeOnCompletion { })) 30 checkCompleteOk(c) 31 assertEquals(false, c.complete(c.invokeOnCompletion { })) 32 checkCompleteOk(c) 33 assertIs<Incomplete>(c.getCompleted()) 34 } 35 checkFreshnull36 private fun checkFresh(c: CompletableDeferred<*>) { 37 assertEquals(true, c.isActive) 38 assertEquals(false, c.isCancelled) 39 assertEquals(false, c.isCompleted) 40 assertThrows<IllegalStateException> { c.getCancellationException() } 41 assertThrows<IllegalStateException> { c.getCompleted() } 42 assertThrows<IllegalStateException> { c.getCompletionExceptionOrNull() } 43 } 44 checkCompleteOknull45 private fun checkCompleteOk(c: CompletableDeferred<*>) { 46 assertEquals(false, c.isActive) 47 assertEquals(false, c.isCancelled) 48 assertEquals(true, c.isCompleted) 49 assertIs<JobCancellationException>(c.getCancellationException()) 50 assertNull(c.getCompletionExceptionOrNull()) 51 } 52 checkCancelnull53 private fun checkCancel(c: CompletableDeferred<String>) { 54 assertEquals(false, c.isActive) 55 assertEquals(true, c.isCancelled) 56 assertEquals(true, c.isCompleted) 57 assertThrows<CancellationException> { c.getCompleted() } 58 assertIs<CancellationException>(c.getCompletionExceptionOrNull()) 59 } 60 61 @Test testCancelWithExceptionnull62 fun testCancelWithException() { 63 val c = CompletableDeferred<String>() 64 assertEquals(true, c.completeExceptionally(TestException())) 65 checkCancelWithException(c) 66 assertEquals(false, c.completeExceptionally(TestException())) 67 checkCancelWithException(c) 68 } 69 checkCancelWithExceptionnull70 private fun checkCancelWithException(c: CompletableDeferred<String>) { 71 assertEquals(false, c.isActive) 72 assertEquals(true, c.isCancelled) 73 assertEquals(true, c.isCompleted) 74 assertIs<JobCancellationException>(c.getCancellationException()) 75 assertThrows<TestException> { c.getCompleted() } 76 assertIs<TestException>(c.getCompletionExceptionOrNull()) 77 } 78 79 @Test testCompleteWithResultOKnull80 fun testCompleteWithResultOK() { 81 val c = CompletableDeferred<String>() 82 assertEquals(true, c.completeWith(Result.success("OK"))) 83 checkCompleteOk(c) 84 assertEquals("OK", c.getCompleted()) 85 assertEquals(false, c.completeWith(Result.success("OK"))) 86 checkCompleteOk(c) 87 assertEquals("OK", c.getCompleted()) 88 } 89 90 @Test testCompleteWithResultExceptionnull91 fun testCompleteWithResultException() { 92 val c = CompletableDeferred<String>() 93 assertEquals(true, c.completeWith(Result.failure(TestException()))) 94 checkCancelWithException(c) 95 assertEquals(false, c.completeWith(Result.failure(TestException()))) 96 checkCancelWithException(c) 97 } 98 99 @Test testParentCancelsChildnull100 fun testParentCancelsChild() { 101 val parent = Job() 102 val c = CompletableDeferred<String>(parent) 103 checkFresh(c) 104 parent.cancel() 105 assertEquals(false, parent.isActive) 106 assertEquals(true, parent.isCancelled) 107 assertEquals(false, c.isActive) 108 assertEquals(true, c.isCancelled) 109 assertEquals(true, c.isCompleted) 110 assertThrows<CancellationException> { c.getCompleted() } 111 assertIs<CancellationException>(c.getCompletionExceptionOrNull()) 112 } 113 114 @Test testParentActiveOnChildCompletionnull115 fun testParentActiveOnChildCompletion() { 116 val parent = Job() 117 val c = CompletableDeferred<String>(parent) 118 checkFresh(c) 119 assertEquals(true, parent.isActive) 120 assertEquals(true, c.complete("OK")) 121 checkCompleteOk(c) 122 assertEquals(true, parent.isActive) 123 } 124 125 @Test testParentCancelledOnChildExceptionnull126 fun testParentCancelledOnChildException() { 127 val parent = Job() 128 val c = CompletableDeferred<String>(parent) 129 checkFresh(c) 130 assertEquals(true, parent.isActive) 131 assertEquals(true, c.completeExceptionally(TestException())) 132 checkCancelWithException(c) 133 assertEquals(false, parent.isActive) 134 assertEquals(true, parent.isCancelled) 135 } 136 137 @Test testParentActiveOnChildCancellationnull138 fun testParentActiveOnChildCancellation() { 139 val parent = Job() 140 val c = CompletableDeferred<String>(parent) 141 checkFresh(c) 142 assertEquals(true, parent.isActive) 143 c.cancel() 144 checkCancel(c) 145 assertEquals(true, parent.isActive) 146 } 147 148 @Test <lambda>null149 fun testAwait() = runTest { 150 expect(1) 151 val c = CompletableDeferred<String>() 152 launch(start = 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 166 @Test <lambda>null167 fun testCancelAndAwaitParentWaitChildren() = runTest { 168 expect(1) 169 val parent = CompletableDeferred<String>() 170 launch(parent, start = CoroutineStart.UNDISPATCHED) { 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 <lambda>null189 fun testCompleteAndAwaitParentWaitChildren() = runTest { 190 expect(1) 191 val parent = CompletableDeferred<String>() 192 launch(parent, start = CoroutineStart.UNDISPATCHED) { 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 assertThrowsnull207 private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) { 208 try { 209 block() 210 fail("Should not complete normally") 211 } catch (e: Throwable) { 212 assertIs<T>(e) 213 } 214 } 215 } 216