blob: af3115cc0b55d558b0675fb08518ba196b28ef96 [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001/*
2 * Copyright 2016-2017 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Roman Elizarove3f28842017-12-21 19:15:40 +030017@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
18
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030019package kotlinx.coroutines.experimental
20
Roman Elizarov9fe5f462018-02-21 19:05:52 +030021import kotlin.coroutines.experimental.*
Roman Elizarove3f28842017-12-21 19:15:40 +030022import kotlin.test.*
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030023
Roman Elizarovaa461cf2018-04-11 13:20:29 +030024class AsyncLazyTest : TestBase() {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030025 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030026 fun testSimple() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030027 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030028 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030029 expect(3)
30 42
31 }
32 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030033 assertTrue(!d.isActive && !d.isCompleted)
34 assertTrue(d.await() == 42)
35 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030036 expect(4)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030037 assertTrue(d.await() == 42) // second await -- same result
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030038 finish(5)
39 }
40
41 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030042 fun testLazyDeferAndYield() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030043 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030044 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030045 expect(3)
46 yield() // this has not effect, because parent coroutine is waiting
47 expect(4)
48 42
49 }
50 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030051 assertTrue(!d.isActive && !d.isCompleted)
52 assertTrue(d.await() == 42)
53 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030054 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030055 assertTrue(d.await() == 42) // second await -- same result
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030056 finish(6)
57 }
58
59 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +030060 fun testLazyDeferAndYield2() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030061 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030062 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030063 expect(7)
64 42
65 }
66 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030067 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov43e3af72017-07-21 16:01:31 +030068 launch(coroutineContext) { // see how it looks from another coroutine
Roman Elizarov7cf452e2017-01-29 21:58:33 +030069 expect(4)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030070 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030071 yield() // yield back to main
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030072 expect(6)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030073 assertTrue(d.isActive && !d.isCompleted) // implicitly started by main's await
Roman Elizarov7cf452e2017-01-29 21:58:33 +030074 yield() // yield to d
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030075 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030076 expect(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030077 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov32d95322017-02-09 15:57:31 +030078 yield() // yield to second child (lazy async is not computing yet)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030079 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030080 assertTrue(!d.isActive && !d.isCompleted)
81 assertTrue(d.await() == 42) // starts computing
82 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030083 finish(8)
84 }
85
Roman Elizarove3f28842017-12-21 19:15:40 +030086 @Test
87 fun testSimpleException() = runTest(
88 expected = { it is TestException }
89 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030090 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030091 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030092 finish(3)
Roman Elizarove3f28842017-12-21 19:15:40 +030093 throw TestException()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030094 }
95 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +030096 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030097 d.await() // will throw IOException
98 }
99
100 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +0300101 fun testLazyDeferAndYieldException() = runTest(
102 expected = { it is TestException }
103 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300104 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300105 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300106 expect(3)
Roman Elizarove3f28842017-12-21 19:15:40 +0300107 yield() // this has not effect, because parent coroutine is waiting
108 finish(4)
109 throw TestException()
110 }
111 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300112 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarove3f28842017-12-21 19:15:40 +0300113 d.await() // will throw IOException
114 }
115
116 @Test
117 fun testCatchException() = runTest {
118 expect(1)
119 val d = async(coroutineContext, CoroutineStart.LAZY) {
120 expect(3)
121 throw TestException()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300122 }
123 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300124 assertTrue(!d.isActive && !d.isCompleted)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300125 try {
126 d.await() // will throw IOException
Roman Elizarove3f28842017-12-21 19:15:40 +0300127 } catch (e: TestException) {
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300128 assertTrue(!d.isActive && d.isCompleted && d.isCompletedExceptionally && !d.isCancelled)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300129 expect(4)
130 }
131 finish(5)
132 }
133
134 @Test
Roman Elizarove3f28842017-12-21 19:15:40 +0300135 fun testStart() = runTest {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300136 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300137 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300138 expect(4)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300139 42
140 }
141 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300142 assertTrue(!d.isActive && !d.isCompleted)
143 assertTrue(d.start())
144 assertTrue(d.isActive && !d.isCompleted)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300145 expect(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300146 assertTrue(!d.start())
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300147 yield() // yield to started coroutine
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300148 assertTrue(!d.isActive && d.isCompleted && !d.isCompletedExceptionally) // and it finishes
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300149 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300150 assertTrue(d.await() == 42) // await sees result
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300151 finish(6)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300152 }
153
Roman Elizarove3f28842017-12-21 19:15:40 +0300154 @Test
155 fun testCancelBeforeStart() = runTest(
156 expected = { it is JobCancellationException }
157 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300158 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300159 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300160 expectUnreached()
161 42
162 }
163 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300164 assertTrue(!d.isActive && !d.isCompleted)
165 assertTrue(d.cancel())
166 assertTrue(!d.isActive && d.isCompleted && d.isCompletedExceptionally && d.isCancelled)
167 assertTrue(!d.cancel())
168 assertTrue(!d.start())
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300169 finish(3)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300170 assertTrue(d.await() == 42) // await shall throw CancellationException
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300171 expectUnreached()
172 }
173
Roman Elizarove3f28842017-12-21 19:15:40 +0300174 @Test
175 fun testCancelWhileComputing() = runTest(
176 expected = { it is CancellationException }
177 ) {
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300178 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300179 val d = async(coroutineContext, CoroutineStart.LAZY) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300180 expect(4)
181 yield() // yield to main, that is going to cancel us
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300182 expectUnreached()
183 42
184 }
185 expect(2)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300186 assertTrue(!d.isActive && !d.isCompleted && !d.isCancelled)
187 assertTrue(d.start())
188 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300189 expect(3)
190 yield() // yield to d
191 expect(5)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300192 assertTrue(d.isActive && !d.isCompleted && !d.isCancelled)
193 assertTrue(d.cancel())
194 assertTrue(!d.isActive && !d.isCompletedExceptionally && d.isCancelled) // cancelling !
195 assertTrue(!d.cancel())
196 assertTrue(!d.isActive && !d.isCompletedExceptionally && d.isCancelled) // still cancelling
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300197 finish(6)
Roman Elizarovc0d71dc2017-12-21 22:12:43 +0300198 assertTrue(d.await() == 42) // await shall throw CancellationException
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300199 expectUnreached()
200 }
Roman Elizarove3f28842017-12-21 19:15:40 +0300201
202 private class TestException : Exception()
Roman Elizarov41c5c8b2017-01-25 13:37:15 +0300203}