blob: 40590ff4edad405c7d4f2e993eb9bbc0316f9cbc [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03002 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarovf16fd272017-02-07 11:26:00 +03003 */
4
Roman Elizarove3f28842017-12-21 19:15:40 +03005@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
6
Roman Elizarov41c5c8b2017-01-25 13:37:15 +03007package kotlinx.coroutines.experimental
8
Roman Elizarov9fe5f462018-02-21 19:05:52 +03009import kotlin.coroutines.experimental.*
Roman Elizarove3f28842017-12-21 19:15:40 +030010import kotlin.test.*
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030011
Roman Elizarovaa461cf2018-04-11 13:20:29 +030012class AsyncLazyTest : TestBase() {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030013 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030014 fun testSimple() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030015 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030016 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030017 expect(3)
18 42
19 }
20 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030021 assertTrue(!d.isActive && !d.isCompleted)
22 assertTrue(d.await() == 42)
23 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030024 expect(4)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030025 assertTrue(d.await() == 42) // second await -- same result
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030026 finish(5)
27 }
28
29 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030030 fun testLazyDeferAndYield() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030031 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030032 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030033 expect(3)
34 yield() // this has not effect, because parent coroutine is waiting
35 expect(4)
36 42
37 }
38 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030039 assertTrue(!d.isActive && !d.isCompleted)
40 assertTrue(d.await() == 42)
41 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030042 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030043 assertTrue(d.await() == 42) // second await -- same result
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030044 finish(6)
45 }
46
47 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030048 fun testLazyDeferAndYield2() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030049 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030050 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030051 expect(7)
52 42
53 }
54 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030055 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov43e3af72017-07-21 16:01:31 +030056 launch(coroutineContext) { // see how it looks from another coroutine
Roman Elizarov7cf452e2017-01-29 21:58:33 +030057 expect(4)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030058 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030059 yield() // yield back to main
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030060 expect(6)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030061 assertTrue(d.isActive && !d.isCompleted) // implicitly started by main's await
Roman Elizarov7cf452e2017-01-29 21:58:33 +030062 yield() // yield to d
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030063 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030064 expect(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030065 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov32d95322017-02-09 15:57:31 +030066 yield() // yield to second child (lazy async is not computing yet)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030067 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030068 assertTrue(!d.isActive && !d.isCompleted)
69 assertTrue(d.await() == 42) // starts computing
70 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030071 finish(8)
72 }
73
Roman Elizarove3f28842017-12-21 19:15:40 +030074 @Test
75 fun testSimpleException() = runTest(
76 expected = { it is TestException }
77 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030078 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030079 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030080 finish(3)
Roman Elizarove3f28842017-12-21 19:15:40 +030081 throw TestException()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030082 }
83 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030084 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030085 d.await() // will throw IOException
86 }
87
88 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030089 fun testLazyDeferAndYieldException() = runTest(
90 expected = { it is TestException }
91 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030092 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030093 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030094 expect(3)
Roman Elizarove3f28842017-12-21 19:15:40 +030095 yield() // this has not effect, because parent coroutine is waiting
96 finish(4)
97 throw TestException()
98 }
99 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300100 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarove3f28842017-12-21 19:15:40 +0300101 d.await() // will throw IOException
102 }
103
104 @Test
105 fun testCatchException() = runTest {
106 expect(1)
107 val d = async(coroutineContext, CoroutineStart.LAZY) {
108 expect(3)
109 throw TestException()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300110 }
111 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300112 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300113 try {
114 d.await() // will throw IOException
Roman Elizarove3f28842017-12-21 19:15:40 +0300115 } catch (e: TestException) {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300116 assertTrue(!d.isActive && d.isCompleted && d.isCompletedExceptionally && !d.isCancelled)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300117 expect(4)
118 }
119 finish(5)
120 }
121
122 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +0300123 fun testStart() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300124 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300125 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300126 expect(4)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300127 42
128 }
129 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300130 assertTrue(!d.isActive && !d.isCompleted)
131 assertTrue(d.start())
132 assertTrue(d.isActive && !d.isCompleted)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300133 expect(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300134 assertTrue(!d.start())
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300135 yield() // yield to started coroutine
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300136 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally) // and it finishes
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300137 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300138 assertTrue(d.await() == 42) // await sees result
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300139 finish(6)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300140 }
141
Roman Elizarove3f28842017-12-21 19:15:40 +0300142 @Test
143 fun testCancelBeforeStart() = runTest(
144 expected = { it is JobCancellationException }
145 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300146 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300147 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300148 expectUnreached()
149 42
150 }
151 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300152 assertTrue(!d.isActive && !d.isCompleted)
153 assertTrue(d.cancel())
154 assertTrue(!d.isActive && d.isCompleted && d.isCompletedExceptionally && d.isCancelled)
155 assertTrue(!d.cancel())
156 assertTrue(!d.start())
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300157 finish(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300158 assertTrue(d.await() == 42) // await shall throw CancellationException
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300159 expectUnreached()
160 }
161
Roman Elizarove3f28842017-12-21 19:15:40 +0300162 @Test
163 fun testCancelWhileComputing() = runTest(
164 expected = { it is CancellationException }
165 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300166 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300167 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300168 expect(4)
169 yield() // yield to main, that is going to cancel us
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300170 expectUnreached()
171 42
172 }
173 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300174 assertTrue(!d.isActive && !d.isCompleted && !d.isCancelled)
175 assertTrue(d.start())
176 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300177 expect(3)
178 yield() // yield to d
179 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300180 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled)
181 assertTrue(d.cancel())
182 assertTrue(!d.isActive && !d.isCompletedExceptionally && d.isCancelled) // cancelling !
183 assertTrue(!d.cancel())
184 assertTrue(!d.isActive && !d.isCompletedExceptionally && d.isCancelled) // still cancelling
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300185 finish(6)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300186 assertTrue(d.await() == 42) // await shall throw CancellationException
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300187 expectUnreached()
188 }
Roman Elizarove3f28842017-12-21 19:15:40 +0300189
190 private class TestException : Exception()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300191}