1 /* 2 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913 6 7 package kotlinx.coroutines 8 9 import kotlin.test.* 10 11 class CompletableDeferredTest : TestBase() { 12 @Test testFreshnull13 fun testFresh() { 14 val c = CompletableDeferred<String>() 15 checkFresh(c) 16 } 17 18 @Test testCompletenull19 fun testComplete() { 20 val c = CompletableDeferred<String>() 21 assertEquals(true, c.complete("OK")) 22 checkCompleteOk(c) 23 assertEquals("OK", c.getCompleted()) 24 assertEquals(false, c.complete("OK")) 25 checkCompleteOk(c) 26 assertEquals("OK", c.getCompleted()) 27 } 28 29 @Test testCompleteWithIncompleteResultnull30 fun testCompleteWithIncompleteResult() { 31 val c = CompletableDeferred<DisposableHandle>() 32 assertEquals(true, c.complete(c.invokeOnCompletion { })) 33 checkCompleteOk(c) 34 assertEquals(false, c.complete(c.invokeOnCompletion { })) 35 checkCompleteOk(c) 36 assertTrue(c.getCompleted() is Incomplete) 37 } 38 checkFreshnull39 private fun checkFresh(c: CompletableDeferred<*>) { 40 assertEquals(true, c.isActive) 41 assertEquals(false, c.isCancelled) 42 assertEquals(false, c.isCompleted) 43 assertThrows<IllegalStateException> { c.getCancellationException() } 44 assertThrows<IllegalStateException> { c.getCompleted() } 45 assertThrows<IllegalStateException> { c.getCompletionExceptionOrNull() } 46 } 47 checkCompleteOknull48 private fun checkCompleteOk(c: CompletableDeferred<*>) { 49 assertEquals(false, c.isActive) 50 assertEquals(false, c.isCancelled) 51 assertEquals(true, c.isCompleted) 52 assertTrue(c.getCancellationException() is JobCancellationException) 53 assertNull(c.getCompletionExceptionOrNull()) 54 } 55 checkCancelnull56 private fun checkCancel(c: CompletableDeferred<String>) { 57 assertEquals(false, c.isActive) 58 assertEquals(true, c.isCancelled) 59 assertEquals(true, c.isCompleted) 60 assertThrows<CancellationException> { c.getCompleted() } 61 assertTrue(c.getCompletionExceptionOrNull() is CancellationException) 62 } 63 64 @Test testCancelWithExceptionnull65 fun testCancelWithException() { 66 val c = CompletableDeferred<String>() 67 assertEquals(true, c.completeExceptionally(TestException())) 68 checkCancelWithException(c) 69 assertEquals(false, c.completeExceptionally(TestException())) 70 checkCancelWithException(c) 71 } 72 checkCancelWithExceptionnull73 private fun checkCancelWithException(c: CompletableDeferred<String>) { 74 assertEquals(false, c.isActive) 75 assertEquals(true, c.isCancelled) 76 assertEquals(true, c.isCompleted) 77 assertTrue(c.getCancellationException() is JobCancellationException) 78 assertThrows<TestException> { c.getCompleted() } 79 assertTrue(c.getCompletionExceptionOrNull() is TestException) 80 } 81 82 @Test testCompleteWithResultOKnull83 fun testCompleteWithResultOK() { 84 val c = CompletableDeferred<String>() 85 assertEquals(true, c.completeWith(Result.success("OK"))) 86 checkCompleteOk(c) 87 assertEquals("OK", c.getCompleted()) 88 assertEquals(false, c.completeWith(Result.success("OK"))) 89 checkCompleteOk(c) 90 assertEquals("OK", c.getCompleted()) 91 } 92 93 @Test testCompleteWithResultExceptionnull94 fun testCompleteWithResultException() { 95 val c = CompletableDeferred<String>() 96 assertEquals(true, c.completeWith(Result.failure(TestException()))) 97 checkCancelWithException(c) 98 assertEquals(false, c.completeWith(Result.failure(TestException()))) 99 checkCancelWithException(c) 100 } 101 102 @Test testParentCancelsChildnull103 fun testParentCancelsChild() { 104 val parent = Job() 105 val c = CompletableDeferred<String>(parent) 106 checkFresh(c) 107 parent.cancel() 108 assertEquals(false, parent.isActive) 109 assertEquals(true, parent.isCancelled) 110 assertEquals(false, c.isActive) 111 assertEquals(true, c.isCancelled) 112 assertEquals(true, c.isCompleted) 113 assertThrows<CancellationException> { c.getCompleted() } 114 assertTrue(c.getCompletionExceptionOrNull() is CancellationException) 115 } 116 117 @Test testParentActiveOnChildCompletionnull118 fun testParentActiveOnChildCompletion() { 119 val parent = Job() 120 val c = CompletableDeferred<String>(parent) 121 checkFresh(c) 122 assertEquals(true, parent.isActive) 123 assertEquals(true, c.complete("OK")) 124 checkCompleteOk(c) 125 assertEquals(true, parent.isActive) 126 } 127 128 @Test testParentCancelledOnChildExceptionnull129 fun testParentCancelledOnChildException() { 130 val parent = Job() 131 val c = CompletableDeferred<String>(parent) 132 checkFresh(c) 133 assertEquals(true, parent.isActive) 134 assertEquals(true, c.completeExceptionally(TestException())) 135 checkCancelWithException(c) 136 assertEquals(false, parent.isActive) 137 assertEquals(true, parent.isCancelled) 138 } 139 140 @Test testParentActiveOnChildCancellationnull141 fun testParentActiveOnChildCancellation() { 142 val parent = Job() 143 val c = CompletableDeferred<String>(parent) 144 checkFresh(c) 145 assertEquals(true, parent.isActive) 146 c.cancel() 147 checkCancel(c) 148 assertEquals(true, parent.isActive) 149 } 150 151 @Test <lambda>null152 fun testAwait() = runTest { 153 expect(1) 154 val c = CompletableDeferred<String>() 155 launch(start = CoroutineStart.UNDISPATCHED) { 156 expect(2) 157 assertEquals("OK", c.await()) // suspends 158 expect(5) 159 assertEquals("OK", c.await()) // does not suspend 160 expect(6) 161 } 162 expect(3) 163 c.complete("OK") 164 expect(4) 165 yield() // to launch 166 finish(7) 167 } 168 169 @Test <lambda>null170 fun testCancelAndAwaitParentWaitChildren() = runTest { 171 expect(1) 172 val parent = CompletableDeferred<String>() 173 launch(parent, start = CoroutineStart.UNDISPATCHED) { 174 expect(2) 175 try { 176 yield() // will get cancelled 177 } finally { 178 expect(5) 179 } 180 } 181 expect(3) 182 parent.cancel() 183 expect(4) 184 try { 185 parent.await() 186 } catch (e: CancellationException) { 187 finish(6) 188 } 189 } 190 191 @Test <lambda>null192 fun testCompleteAndAwaitParentWaitChildren() = runTest { 193 expect(1) 194 val parent = CompletableDeferred<String>() 195 launch(parent, start = CoroutineStart.UNDISPATCHED) { 196 expect(2) 197 try { 198 yield() // will get cancelled 199 } finally { 200 expect(5) 201 } 202 } 203 expect(3) 204 parent.complete("OK") 205 expect(4) 206 assertEquals("OK", parent.await()) 207 finish(6) 208 } 209 assertThrowsnull210 private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) { 211 try { 212 block() 213 fail("Should not complete normally") 214 } catch (e: Throwable) { 215 assertTrue(e is T) 216 } 217 } 218 }