blob: ffa8ffcbd6cb37fe4dd2bdcbde57171dd653a5ec [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 Elizarov53a0a402017-01-19 20:21:57 +030017package kotlinx.coroutines.experimental
18
Roman Elizarov53a0a402017-01-19 20:21:57 +030019import org.junit.Test
Roman Elizarov58a7add2017-01-20 12:19:52 +030020import java.io.IOException
Roman Elizarov53a0a402017-01-19 20:21:57 +030021
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030022class CoroutinesTest : TestBase() {
Roman Elizarov53a0a402017-01-19 20:21:57 +030023 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030024 fun testSimple() = runBlocking {
Roman Elizarov53a0a402017-01-19 20:21:57 +030025 expect(1)
26 finish(2)
27 }
28
29 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030030 fun testYield() = runBlocking {
Roman Elizarov53a0a402017-01-19 20:21:57 +030031 expect(1)
32 yield() // effectively does nothing, as we don't have other coroutines
33 finish(2)
34 }
35
36 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030037 fun testLaunchAndYieldJoin() = runBlocking {
Roman Elizarov53a0a402017-01-19 20:21:57 +030038 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +030039 val job = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030040 expect(3)
Roman Elizarov53a0a402017-01-19 20:21:57 +030041 yield()
42 expect(4)
43 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030044 expect(2)
Roman Elizarov53a0a402017-01-19 20:21:57 +030045 job.join()
46 finish(5)
47 }
Roman Elizarov58a7add2017-01-20 12:19:52 +030048
49 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030050 fun testNested() = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +030051 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +030052 val j1 = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030053 expect(3)
Roman Elizarovd528e3e2017-01-23 15:40:05 +030054 val j2 = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030055 expect(5)
Roman Elizarov58a7add2017-01-20 12:19:52 +030056 }
57 expect(4)
58 j2.join()
Roman Elizarov7cf452e2017-01-29 21:58:33 +030059 expect(6)
Roman Elizarov58a7add2017-01-20 12:19:52 +030060 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030061 expect(2)
Roman Elizarov58a7add2017-01-20 12:19:52 +030062 j1.join()
Roman Elizarov7cf452e2017-01-29 21:58:33 +030063 finish(7)
Roman Elizarov58a7add2017-01-20 12:19:52 +030064 }
65
66 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030067 fun testCancelChildImplicit() = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +030068 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +030069 launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030070 expect(3)
Roman Elizarov58a7add2017-01-20 12:19:52 +030071 yield() // parent finishes earlier, does not wait for us
72 expectUnreached()
73 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030074 expect(2)
75 yield()
76 finish(4)
Roman Elizarov58a7add2017-01-20 12:19:52 +030077 }
78
79 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +030080 fun testCancelChildExplicit() = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +030081 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +030082 val job = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030083 expect(3)
Roman Elizarov58a7add2017-01-20 12:19:52 +030084 yield()
85 expectUnreached()
86 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030087 expect(2)
88 yield()
89 expect(4)
Roman Elizarov58a7add2017-01-20 12:19:52 +030090 job.cancel()
Roman Elizarov7cf452e2017-01-29 21:58:33 +030091 finish(5)
92 }
93
94 @Test
95 fun testCancelChildWithFinally() = runBlocking {
96 expect(1)
97 val job = launch(context) {
98 expect(3)
99 try {
100 yield()
101 } finally {
102 finish(6) // cancelled child will still execute finally
103 }
104 expectUnreached()
105 }
106 expect(2)
107 yield()
108 expect(4)
109 job.cancel()
110 expect(5)
Roman Elizarov58a7add2017-01-20 12:19:52 +0300111 }
112
113 @Test
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300114 fun testCancelNestedImplicit() = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +0300115 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300116 val j1 = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300117 expect(3)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300118 val j2 = launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300119 expect(6)
Roman Elizarov58a7add2017-01-20 12:19:52 +0300120 yield() // parent finishes earlier, does not wait for us
121 expectUnreached()
122 }
123 expect(4)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300124 yield()
125 expect(7)
126 yield() // does not go further, because already cancelled
Roman Elizarov58a7add2017-01-20 12:19:52 +0300127 expectUnreached()
128 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300129 expect(2)
130 yield()
131 expect(5)
132 yield()
133 finish(8)
Roman Elizarov58a7add2017-01-20 12:19:52 +0300134 }
135
136 @Test(expected = IOException::class)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300137 fun testExceptionPropagation(): Unit = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +0300138 finish(1)
139 throw IOException()
140 }
141
Roman Elizarovb7c46de2017-02-08 12:35:24 +0300142 @Test(expected = IOException::class)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300143 fun testCancelParentOnChildException(): Unit = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +0300144 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300145 launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300146 finish(3)
Roman Elizarov58a7add2017-01-20 12:19:52 +0300147 throw IOException() // does not propagate exception to launch, but cancels parent (!)
148 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300149 expect(2)
150 yield()
151 expectUnreached() // because of exception in child
Roman Elizarov58a7add2017-01-20 12:19:52 +0300152 }
153
Roman Elizarovb7c46de2017-02-08 12:35:24 +0300154 @Test(expected = IOException::class)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300155 fun testCancelParentOnNestedException(): Unit = runBlocking {
Roman Elizarov58a7add2017-01-20 12:19:52 +0300156 expect(1)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300157 launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300158 expect(3)
Roman Elizarovd528e3e2017-01-23 15:40:05 +0300159 launch(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300160 finish(6)
Roman Elizarov58a7add2017-01-20 12:19:52 +0300161 throw IOException() // unhandled exception kills all parents
162 }
163 expect(4)
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300164 yield()
165 expectUnreached() // because of exception in child
Roman Elizarov58a7add2017-01-20 12:19:52 +0300166 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +0300167 expect(2)
168 yield()
169 expect(5)
170 yield()
171 expectUnreached() // because of exception in child
Roman Elizarov58a7add2017-01-20 12:19:52 +0300172 }
Roman Elizarov58a7add2017-01-20 12:19:52 +0300173}