| /* |
| * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. |
| */ |
| |
| @file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913 |
| |
| package kotlinx.coroutines.experimental |
| |
| import kotlin.coroutines.experimental.* |
| import kotlin.test.* |
| |
| class CompletableDeferredTest : TestBase() { |
| @Test |
| fun testFresh() { |
| val c = CompletableDeferred<String>() |
| checkFresh(c) |
| } |
| |
| private fun checkFresh(c: CompletableDeferred<String>) { |
| assertEquals(true, c.isActive) |
| assertEquals(false, c.isCancelled) |
| assertEquals(false, c.isCompleted) |
| assertEquals(false, c.isCompletedExceptionally) |
| assertThrows<IllegalStateException> { c.getCancellationException() } |
| assertThrows<IllegalStateException> { c.getCompleted() } |
| assertThrows<IllegalStateException> { c.getCompletionExceptionOrNull() } |
| } |
| |
| @Test |
| fun testComplete() { |
| val c = CompletableDeferred<String>() |
| assertEquals(true, c.complete("OK")) |
| checkCompleteOk(c) |
| assertEquals(false, c.complete("OK")) |
| checkCompleteOk(c) |
| } |
| |
| private fun checkCompleteOk(c: CompletableDeferred<String>) { |
| assertEquals(false, c.isActive) |
| assertEquals(false, c.isCancelled) |
| assertEquals(true, c.isCompleted) |
| assertEquals(false, c.isCompletedExceptionally) |
| assertTrue(c.getCancellationException() is JobCancellationException) |
| assertEquals("OK", c.getCompleted()) |
| assertEquals(null, c.getCompletionExceptionOrNull()) |
| } |
| |
| @Test |
| fun testCompleteWithException() { |
| val c = CompletableDeferred<String>() |
| assertEquals(true, c.completeExceptionally(TestException())) |
| checkCompleteTestException(c) |
| assertEquals(false, c.completeExceptionally(TestException())) |
| checkCompleteTestException(c) |
| } |
| |
| private fun checkCompleteTestException(c: CompletableDeferred<String>) { |
| assertEquals(false, c.isActive) |
| assertEquals(false, c.isCancelled) |
| assertEquals(true, c.isCompleted) |
| assertEquals(true, c.isCompletedExceptionally) |
| assertTrue(c.getCancellationException() is JobCancellationException) |
| assertThrows<TestException> { c.getCompleted() } |
| assertTrue(c.getCompletionExceptionOrNull() is TestException) |
| } |
| |
| @Test |
| fun testCancel() { |
| val c = CompletableDeferred<String>() |
| assertEquals(true, c.cancel()) |
| checkCancel(c) |
| assertEquals(false, c.cancel()) |
| checkCancel(c) |
| } |
| |
| private fun checkCancel(c: CompletableDeferred<String>) { |
| assertEquals(false, c.isActive) |
| assertEquals(true, c.isCancelled) |
| assertEquals(true, c.isCompleted) |
| assertEquals(true, c.isCompletedExceptionally) |
| assertThrows<CancellationException> { c.getCompleted() } |
| assertTrue(c.getCompletionExceptionOrNull() is CancellationException) |
| } |
| |
| @Test |
| fun testCancelWithException() { |
| val c = CompletableDeferred<String>() |
| assertEquals(true, c.cancel(TestException())) |
| checkCancelWithException(c) |
| assertEquals(false, c.cancel(TestException())) |
| checkCancelWithException(c) |
| } |
| |
| private fun checkCancelWithException(c: CompletableDeferred<String>) { |
| assertEquals(false, c.isActive) |
| assertEquals(true, c.isCancelled) |
| assertEquals(true, c.isCompleted) |
| assertEquals(true, c.isCompletedExceptionally) |
| assertTrue(c.getCancellationException() is JobCancellationException) |
| assertThrows<TestException> { c.getCompleted() } |
| assertTrue(c.getCompletionExceptionOrNull() is TestException) |
| } |
| |
| @Test |
| fun testParentCancelsChild() { |
| val parent = Job() |
| val c = CompletableDeferred<String>(parent) |
| checkFresh(c) |
| parent.cancel() |
| assertEquals(false, parent.isActive) |
| assertEquals(true, parent.isCancelled) |
| checkCancel(c) |
| } |
| |
| @Test |
| fun testParentActiveOnChildCompletion() { |
| val parent = Job() |
| val c = CompletableDeferred<String>(parent) |
| checkFresh(c) |
| assertEquals(true, parent.isActive) |
| assertEquals(true, c.complete("OK")) |
| checkCompleteOk(c) |
| assertEquals(true, parent.isActive) |
| } |
| |
| @Test |
| fun testParentActiveOnChildException() { |
| val parent = Job() |
| val c = CompletableDeferred<String>(parent) |
| checkFresh(c) |
| assertEquals(true, parent.isActive) |
| assertEquals(true, c.completeExceptionally(TestException())) |
| checkCompleteTestException(c) |
| assertEquals(true, parent.isActive) |
| } |
| |
| @Test |
| fun testParentActiveOnChildCancellation() { |
| val parent = Job() |
| val c = CompletableDeferred<String>(parent) |
| checkFresh(c) |
| assertEquals(true, parent.isActive) |
| assertEquals(true, c.cancel()) |
| checkCancel(c) |
| assertEquals(true, parent.isActive) |
| } |
| |
| @Test |
| fun testAwait() = runTest { |
| expect(1) |
| val c = CompletableDeferred<String>() |
| launch(coroutineContext, CoroutineStart.UNDISPATCHED) { |
| expect(2) |
| assertEquals("OK", c.await()) // suspends |
| expect(5) |
| assertEquals("OK", c.await()) // does not suspend |
| expect(6) |
| } |
| expect(3) |
| c.complete("OK") |
| expect(4) |
| yield() // to launch |
| finish(7) |
| } |
| |
| @Test |
| fun testCancelAndAwaitParentWaitChildren() = runTest { |
| expect(1) |
| val parent = CompletableDeferred<String>() |
| launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) { |
| expect(2) |
| try { |
| yield() // will get cancelled |
| } finally { |
| expect(5) |
| } |
| } |
| expect(3) |
| parent.cancel() |
| expect(4) |
| try { |
| parent.await() |
| } catch (e: CancellationException) { |
| finish(6) |
| } |
| } |
| |
| @Test |
| fun testCompleteAndAwaitParentWaitChildren() = runTest { |
| expect(1) |
| val parent = CompletableDeferred<String>() |
| launch(coroutineContext, start = CoroutineStart.UNDISPATCHED, parent = parent) { |
| expect(2) |
| try { |
| yield() // will get cancelled |
| } finally { |
| expect(5) |
| } |
| } |
| expect(3) |
| parent.complete("OK") |
| expect(4) |
| assertEquals("OK", parent.await()) |
| finish(6) |
| } |
| |
| private inline fun <reified T: Throwable> assertThrows(block: () -> Unit) { |
| try { |
| block() |
| fail("Should not complete normally") |
| } catch (e: Throwable) { |
| assertTrue(e is T) |
| } |
| } |
| |
| class TestException : Throwable() |
| } |