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