Roman Elizarov | f16fd27 | 2017-02-07 11:26:00 +0300 | [diff] [blame] | 1 | /* |
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 Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 17 | package kotlinx.coroutines.experimental |
18 | |||||
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 19 | import org.junit.Test |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 20 | import java.io.IOException |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 21 | |
Roman Elizarov | 41c5c8b | 2017-01-25 13:37:15 +0300 | [diff] [blame] | 22 | class CoroutinesTest : TestBase() { |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 23 | @Test |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 24 | fun testSimple() = runBlocking { |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 25 | expect(1) |
26 | finish(2) | ||||
27 | } | ||||
28 | |||||
29 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 30 | fun testYield() = runBlocking { |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 31 | expect(1) |
32 | yield() // effectively does nothing, as we don't have other coroutines | ||||
33 | finish(2) | ||||
34 | } | ||||
35 | |||||
36 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 37 | fun testLaunchAndYieldJoin() = runBlocking { |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 38 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 39 | val job = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 40 | expect(3) |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 41 | yield() |
42 | expect(4) | ||||
43 | } | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 44 | expect(2) |
Roman Elizarov | 53a0a40 | 2017-01-19 20:21:57 +0300 | [diff] [blame] | 45 | job.join() |
46 | finish(5) | ||||
47 | } | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 48 | |
49 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 50 | fun testNested() = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 51 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 52 | val j1 = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 53 | expect(3) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 54 | val j2 = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 55 | expect(5) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 56 | } |
57 | expect(4) | ||||
58 | j2.join() | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 59 | expect(6) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 60 | } |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 61 | expect(2) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 62 | j1.join() |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 63 | finish(7) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 64 | } |
65 | |||||
66 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 67 | fun testCancelChildImplicit() = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 68 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 69 | launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 70 | expect(3) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 71 | yield() // parent finishes earlier, does not wait for us |
72 | expectUnreached() | ||||
73 | } | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 74 | expect(2) |
75 | yield() | ||||
76 | finish(4) | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 77 | } |
78 | |||||
79 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 80 | fun testCancelChildExplicit() = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 81 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 82 | val job = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 83 | expect(3) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 84 | yield() |
85 | expectUnreached() | ||||
86 | } | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 87 | expect(2) |
88 | yield() | ||||
89 | expect(4) | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 90 | job.cancel() |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 91 | 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 Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 111 | } |
112 | |||||
113 | @Test | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 114 | fun testCancelNestedImplicit() = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 115 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 116 | val j1 = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 117 | expect(3) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 118 | val j2 = launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 119 | expect(6) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 120 | yield() // parent finishes earlier, does not wait for us |
121 | expectUnreached() | ||||
122 | } | ||||
123 | expect(4) | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 124 | yield() |
125 | expect(7) | ||||
126 | yield() // does not go further, because already cancelled | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 127 | expectUnreached() |
128 | } | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 129 | expect(2) |
130 | yield() | ||||
131 | expect(5) | ||||
132 | yield() | ||||
133 | finish(8) | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 134 | } |
135 | |||||
136 | @Test(expected = IOException::class) | ||||
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 137 | fun testExceptionPropagation(): Unit = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 138 | finish(1) |
139 | throw IOException() | ||||
140 | } | ||||
141 | |||||
Roman Elizarov | b7c46de | 2017-02-08 12:35:24 +0300 | [diff] [blame^] | 142 | @Test(expected = IOException::class) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 143 | fun testCancelParentOnChildException(): Unit = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 144 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 145 | launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 146 | finish(3) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 147 | throw IOException() // does not propagate exception to launch, but cancels parent (!) |
148 | } | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 149 | expect(2) |
150 | yield() | ||||
151 | expectUnreached() // because of exception in child | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 152 | } |
153 | |||||
Roman Elizarov | b7c46de | 2017-02-08 12:35:24 +0300 | [diff] [blame^] | 154 | @Test(expected = IOException::class) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 155 | fun testCancelParentOnNestedException(): Unit = runBlocking { |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 156 | expect(1) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 157 | launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 158 | expect(3) |
Roman Elizarov | d528e3e | 2017-01-23 15:40:05 +0300 | [diff] [blame] | 159 | launch(context) { |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 160 | finish(6) |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 161 | throw IOException() // unhandled exception kills all parents |
162 | } | ||||
163 | expect(4) | ||||
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 164 | yield() |
165 | expectUnreached() // because of exception in child | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 166 | } |
Roman Elizarov | 7cf452e | 2017-01-29 21:58:33 +0300 | [diff] [blame] | 167 | expect(2) |
168 | yield() | ||||
169 | expect(5) | ||||
170 | yield() | ||||
171 | expectUnreached() // because of exception in child | ||||
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 172 | } |
Roman Elizarov | 58a7add | 2017-01-20 12:19:52 +0300 | [diff] [blame] | 173 | } |