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") // KT-21913 6 7 package kotlinx.coroutines 8 9 import kotlin.test.* 10 11 class AsyncLazyTest : TestBase() { 12 13 @Test 14 fun testSimple() = runTest { 15 expect(1) 16 val d = async(start = CoroutineStart.LAZY) { 17 expect(3) 18 42 19 } 20 expect(2) 21 assertTrue(!d.isActive && !d.isCompleted) 22 assertEquals(d.await(), 42) 23 assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) 24 expect(4) 25 assertEquals(d.await(), 42) // second await -- same result 26 finish(5) 27 } 28 29 @Test 30 fun testLazyDeferAndYield() = runTest { 31 expect(1) 32 val d = async(start = CoroutineStart.LAZY) { 33 expect(3) 34 yield() // this has not effect, because parent coroutine is waiting 35 expect(4) 36 42 37 } 38 expect(2) 39 assertTrue(!d.isActive && !d.isCompleted) 40 assertEquals(d.await(), 42) 41 assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) 42 expect(5) 43 assertEquals(d.await(), 42) // second await -- same result 44 finish(6) 45 } 46 47 @Test 48 fun testLazyDeferAndYield2() = runTest { 49 expect(1) 50 val d = async(start = CoroutineStart.LAZY) { 51 expect(7) 52 42 53 } 54 expect(2) 55 assertTrue(!d.isActive && !d.isCompleted) 56 launch { // see how it looks from another coroutine 57 expect(4) 58 assertTrue(!d.isActive && !d.isCompleted) 59 yield() // yield back to main 60 expect(6) 61 assertTrue(d.isActive && !d.isCompleted) // implicitly started by main's await 62 yield() // yield to d 63 } 64 expect(3) 65 assertTrue(!d.isActive && !d.isCompleted) 66 yield() // yield to second child (lazy async is not computing yet) 67 expect(5) 68 assertTrue(!d.isActive && !d.isCompleted) 69 assertEquals(d.await(), 42) // starts computing 70 assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) 71 finish(8) 72 } 73 74 @Test 75 fun testSimpleException() = runTest( 76 expected = { it is TestException } 77 ) { 78 expect(1) 79 val d = async(start = CoroutineStart.LAZY) { 80 finish(3) 81 throw TestException() 82 } 83 expect(2) 84 assertTrue(!d.isActive && !d.isCompleted) 85 d.await() // will throw IOException 86 } 87 88 @Test 89 fun testLazyDeferAndYieldException() = runTest( 90 expected = { it is TestException } 91 ) { 92 expect(1) 93 val d = async(start = CoroutineStart.LAZY) { 94 expect(3) 95 yield() // this has not effect, because parent coroutine is waiting 96 finish(4) 97 throw TestException() 98 } 99 expect(2) 100 assertTrue(!d.isActive && !d.isCompleted) 101 d.await() // will throw IOException 102 } 103 104 @Test 105 fun testCatchException() = runTest { 106 expect(1) 107 val d = async(NonCancellable, start = CoroutineStart.LAZY) { 108 expect(3) 109 throw TestException() 110 } 111 expect(2) 112 assertTrue(!d.isActive && !d.isCompleted) 113 try { 114 d.await() // will throw IOException 115 } catch (e: TestException) { 116 assertTrue(!d.isActive && d.isCompleted && d.isCancelled) 117 expect(4) 118 } 119 finish(5) 120 } 121 122 @Test 123 fun testStart() = runTest { 124 expect(1) 125 val d = async(start = CoroutineStart.LAZY) { 126 expect(4) 127 42 128 } 129 expect(2) 130 assertTrue(!d.isActive && !d.isCompleted) 131 assertTrue(d.start()) 132 assertTrue(d.isActive && !d.isCompleted) 133 expect(3) 134 assertTrue(!d.start()) 135 yield() // yield to started coroutine 136 assertTrue(!d.isActive && d.isCompleted && !d.isCancelled) // and it finishes 137 expect(5) 138 assertEquals(d.await(), 42) // await sees result 139 finish(6) 140 } 141 142 @Test 143 fun testCancelBeforeStart() = runTest( 144 expected = { it is CancellationException } 145 ) { 146 expect(1) 147 val d = async(start = CoroutineStart.LAZY) { 148 expectUnreached() 149 42 150 } 151 expect(2) 152 assertTrue(!d.isActive && !d.isCompleted) 153 d.cancel() 154 assertTrue(!d.isActive && d.isCompleted && d.isCancelled) 155 assertTrue(!d.start()) 156 finish(3) 157 assertEquals(d.await(), 42) // await shall throw CancellationException 158 expectUnreached() 159 } 160 161 @Test 162 fun testCancelWhileComputing() = runTest( 163 expected = { it is CancellationException } 164 ) { 165 expect(1) 166 val d = async(start = CoroutineStart.LAZY) { 167 expect(4) 168 yield() // yield to main, that is going to cancel us 169 expectUnreached() 170 42 171 } 172 expect(2) 173 assertTrue(!d.isActive && !d.isCompleted && !d.isCancelled) 174 assertTrue(d.start()) 175 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled) 176 expect(3) 177 yield() // yield to d 178 expect(5) 179 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled) 180 d.cancel() 181 assertTrue(!d.isActive && d.isCancelled) // cancelling ! 182 assertTrue(!d.isActive && d.isCancelled) // still cancelling 183 finish(6) 184 assertEquals(d.await(), 42) // await shall throw CancellationException 185 expectUnreached() 186 } 187 }