/* * 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 import kotlin.test.* class AsyncLazyTest : TestBase() { @Test fun testSimple() = runTest { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(3) 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted) assertEquals(d.await(), 42) assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) expect(4) assertEquals(d.await(), 42) // second await -- same result finish(5) } @Test fun testLazyDeferAndYield() = runTest { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(3) yield() // this has not effect, because parent coroutine is waiting expect(4) 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted) assertEquals(d.await(), 42) assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) expect(5) assertEquals(d.await(), 42) // second await -- same result finish(6) } @Test fun testLazyDeferAndYield2() = runTest { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(7) 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted) launch { // see how it looks from another coroutine expect(4) assertTrue(!d.isActive && !d.isCompleted) yield() // yield back to main expect(6) assertTrue(d.isActive && !d.isCompleted) // implicitly started by main's await yield() // yield to d } expect(3) assertTrue(!d.isActive && !d.isCompleted) yield() // yield to second child (lazy async is not computing yet) expect(5) assertTrue(!d.isActive && !d.isCompleted) assertEquals(d.await(), 42) // starts computing assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) finish(8) } @Test fun testSimpleException() = runTest( expected = { it is TestException } ) { expect(1) val d = async(start = CoroutineStart.LAZY) { finish(3) throw TestException() } expect(2) assertTrue(!d.isActive && !d.isCompleted) d.await() // will throw IOException } @Test fun testLazyDeferAndYieldException() = runTest( expected = { it is TestException } ) { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(3) yield() // this has not effect, because parent coroutine is waiting finish(4) throw TestException() } expect(2) assertTrue(!d.isActive && !d.isCompleted) d.await() // will throw IOException } @Test fun testCatchException() = runTest { expect(1) val d = async(NonCancellable, start = CoroutineStart.LAZY) { expect(3) throw TestException() } expect(2) assertTrue(!d.isActive && !d.isCompleted) try { d.await() // will throw IOException } catch (e: TestException) { assertTrue(!d.isActive && d.isCompleted && d.isCancelled) expect(4) } finish(5) } @Test fun testStart() = runTest { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(4) 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted) assertTrue(d.start()) assertTrue(d.isActive && !d.isCompleted) expect(3) assertTrue(!d.start()) yield() // yield to started coroutine assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) // and it finishes expect(5) assertEquals(d.await(), 42) // await sees result finish(6) } @Test fun testCancelBeforeStart() = runTest( expected = { it is CancellationException } ) { expect(1) val d = async(start = CoroutineStart.LAZY) { expectUnreached() 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted) d.cancel() assertTrue(!d.isActive && d.isCompleted && d.isCancelled) assertTrue(!d.start()) finish(3) assertEquals(d.await(), 42) // await shall throw CancellationException expectUnreached() } @Test fun testCancelWhileComputing() = runTest( expected = { it is CancellationException } ) { expect(1) val d = async(start = CoroutineStart.LAZY) { expect(4) yield() // yield to main, that is going to cancel us expectUnreached() 42 } expect(2) assertTrue(!d.isActive && !d.isCompleted && !d.isCancelled) assertTrue(d.start()) assertTrue(d.isActive && !d.isCompleted && !d.isCancelled) expect(3) yield() // yield to d expect(5) assertTrue(d.isActive && !d.isCompleted && !d.isCancelled) d.cancel() assertTrue(!d.isActive && d.isCancelled) // cancelling ! assertTrue(!d.isActive && d.isCancelled) // still cancelling finish(6) assertEquals(d.await(), 42) // await shall throw CancellationException expectUnreached() } }