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 13 fun testFresh() { 14 val c = CompletableDeferred<String>() 15 checkFresh(c) 16 } 17 18 @Test 19 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 30 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 39 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 48 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 assertEquals(null, c.getCompletionExceptionOrNull()) 54 } 55 56 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 65 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 73 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 83 fun testParentCancelsChild() { 84 val parent = Job() 85 val c = CompletableDeferred<String>(parent) 86 checkFresh(c) 87 parent.cancel() 88 assertEquals(false, parent.isActive) 89 assertEquals(true, parent.isCancelled) 90 assertEquals(false, c.isActive) 91 assertEquals(true, c.isCancelled) 92 assertEquals(true, c.isCompleted) 93 assertThrows<CancellationException> { c.getCompleted() } 94 assertTrue(c.getCompletionExceptionOrNull() is CancellationException) 95 } 96 97 @Test 98 fun testParentActiveOnChildCompletion() { 99 val parent = Job() 100 val c = CompletableDeferred<String>(parent) 101 checkFresh(c) 102 assertEquals(true, parent.isActive) 103 assertEquals(true, c.complete("OK")) 104 checkCompleteOk(c) 105 assertEquals(true, parent.isActive) 106 } 107 108 @Test 109 fun testParentCancelledOnChildException() { 110 val parent = Job() 111 val c = CompletableDeferred<String>(parent) 112 checkFresh(c) 113 assertEquals(true, parent.isActive) 114 assertEquals(true, c.completeExceptionally(TestException())) 115 checkCancelWithException(c) 116 assertEquals(false, parent.isActive) 117 assertEquals(true, parent.isCancelled) 118 } 119 120 @Test 121 fun testParentActiveOnChildCancellation() { 122 val parent = Job() 123 val c = CompletableDeferred<String>(parent) 124 checkFresh(c) 125 assertEquals(true, parent.isActive) 126 c.cancel() 127 checkCancel(c) 128 assertEquals(true, parent.isActive) 129 } 130 131 @Test 132 fun testAwait() = runTest { 133 expect(1) 134 val c = CompletableDeferred<String>() 135 launch(start = CoroutineStart.UNDISPATCHED) { 136 expect(2) 137 assertEquals("OK", c.await()) // suspends 138 expect(5) 139 assertEquals("OK", c.await()) // does not suspend 140 expect(6) 141 } 142 expect(3) 143 c.complete("OK") 144 expect(4) 145 yield() // to launch 146 finish(7) 147 } 148 149 @Test 150 fun testCancelAndAwaitParentWaitChildren() = runTest { 151 expect(1) 152 val parent = CompletableDeferred<String>() 153 launch(parent, start = CoroutineStart.UNDISPATCHED) { 154 expect(2) 155 try { 156 yield() // will get cancelled 157 } finally { 158 expect(5) 159 } 160 } 161 expect(3) 162 parent.cancel() 163 expect(4) 164 try { 165 parent.await() 166 } catch (e: CancellationException) { 167 finish(6) 168 } 169 } 170 171 @Test 172 fun testCompleteAndAwaitParentWaitChildren() = runTest { 173 expect(1) 174 val parent = CompletableDeferred<String>() 175 launch(parent, start = CoroutineStart.UNDISPATCHED) { 176 expect(2) 177 try { 178 yield() // will get cancelled 179 } finally { 180 expect(5) 181 } 182 } 183 expect(3) 184 parent.complete("OK") 185 expect(4) 186 assertEquals("OK", parent.await()) 187 finish(6) 188 } 189 190 private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) { 191 try { 192 block() 193 fail("Should not complete normally") 194 } catch (e: Throwable) { 195 assertTrue(e is T) 196 } 197 } 198 }