blob: 6e6c50818bb994031414a254c1c2e1b964186c4c [file] [log] [blame]
Roman Elizarov1216e912017-02-22 09:57:06 +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
17package kotlinx.coroutines.experimental.selects
18
Roman Elizarov9fe5f462018-02-21 19:05:52 +030019import kotlinx.coroutines.experimental.*
20import kotlinx.coroutines.experimental.channels.*
21import kotlinx.coroutines.experimental.intrinsics.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030022import kotlin.coroutines.experimental.*
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030023import kotlin.test.*
Roman Elizarov1216e912017-02-22 09:57:06 +030024
25class SelectArrayChannelTest : TestBase() {
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030026
Roman Elizarov1216e912017-02-22 09:57:06 +030027 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030028 fun testSelectSendSuccess() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030029 expect(1)
30 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030031 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030032 expect(2)
33 assertEquals("OK", channel.receive())
34 finish(6)
35 }
36 yield() // to launched coroutine
37 expect(3)
38 select<Unit> {
39 channel.onSend("OK") {
40 expect(4)
41 }
42 }
43 expect(5)
44 }
45
46 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030047 fun testSelectSendSuccessWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030048 expect(1)
49 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030050 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030051 expect(2)
52 assertEquals("OK", channel.receive())
53 finish(6)
54 }
55 yield() // to launched coroutine
56 expect(3)
57 select<Unit> {
58 channel.onSend("OK") {
59 expect(4)
60 }
61 default {
62 expectUnreached()
63 }
64 }
65 expect(5)
66 }
67
68 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030069 fun testSelectSendReceiveBuf() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030070 expect(1)
71 val channel = ArrayChannel<String>(1)
72 select<Unit> {
73 channel.onSend("OK") {
74 expect(2)
75 }
76 }
77 expect(3)
78 select<Unit> {
79 channel.onReceive { v ->
80 expect(4)
81 assertEquals("OK", v)
82 }
83 }
84 finish(5)
85 }
86
87 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030088 fun testSelectSendWait() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030089 expect(1)
90 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030091 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030092 expect(4)
93 assertEquals("BUF", channel.receive())
94 expect(5)
95 assertEquals("OK", channel.receive())
96 expect(6)
97 }
98 expect(2)
99 channel.send("BUF")
100 expect(3)
101 select<Unit> {
102 channel.onSend("OK") {
103 expect(7)
104 }
105 }
106 finish(8)
107 }
108
109 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300110 fun testSelectReceiveSuccess() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300111 expect(1)
112 val channel = ArrayChannel<String>(1)
113 channel.send("OK")
114 expect(2)
115 select<Unit> {
116 channel.onReceive { v ->
117 expect(3)
118 assertEquals("OK", v)
119 }
120 }
121 finish(4)
122 }
123
124 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300125 fun testSelectReceiveSuccessWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300126 expect(1)
127 val channel = ArrayChannel<String>(1)
128 channel.send("OK")
129 expect(2)
130 select<Unit> {
131 channel.onReceive { v ->
132 expect(3)
133 assertEquals("OK", v)
134 }
135 default {
136 expectUnreached()
137 }
138 }
139 finish(4)
140 }
141
142 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300143 fun testSelectReceiveWaitWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300144 expect(1)
145 val channel = ArrayChannel<String>(1)
146 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300147 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300148 expectUnreached()
149 }
150 default {
151 expect(2)
152 }
153 }
154 expect(3)
155 channel.send("BUF")
156 expect(4)
157 // make sure second send blocks (select above is over)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300158 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300159 expect(6)
160 channel.send("CHK")
161 finish(10)
162 }
163 expect(5)
164 yield()
165 expect(7)
166 assertEquals("BUF", channel.receive())
167 expect(8)
168 assertEquals("CHK", channel.receive())
169 expect(9)
170 }
171
172 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300173 fun testSelectReceiveWait() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300174 expect(1)
175 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300176 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300177 expect(3)
178 channel.send("OK")
179 expect(4)
180 }
181 expect(2)
182 select<Unit> {
183 channel.onReceive { v ->
184 expect(5)
185 assertEquals("OK", v)
186 }
187 }
188 finish(6)
189 }
190
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300191 @Test
192 fun testSelectReceiveClosed() = runTest({it is ClosedReceiveChannelException}) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300193 expect(1)
194 val channel = ArrayChannel<String>(1)
195 channel.close()
196 finish(2)
197 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300198 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300199 expectUnreached()
200 }
201 }
202 expectUnreached()
203 }
204
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300205 @Test
206 fun testSelectReceiveWaitClosed() = runTest({it is ClosedReceiveChannelException}) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300207 expect(1)
208 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300209 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300210 expect(3)
211 channel.close()
212 finish(4)
213 }
214 expect(2)
215 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300216 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300217 expectUnreached()
218 }
219 }
220 expectUnreached()
221 }
222
223 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300224 fun testSelectSendResourceCleanup() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300225 val channel = ArrayChannel<Int>(1)
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300226 val n = 1000
Roman Elizarov1216e912017-02-22 09:57:06 +0300227 expect(1)
228 channel.send(-1) // fill the buffer, so all subsequent sends cannot proceed
229 repeat(n) { i ->
230 select {
231 channel.onSend(i) { expectUnreached() }
232 default { expect(i + 2) }
233 }
234 }
235 finish(n + 2)
236 }
237
238 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300239 fun testSelectReceiveResourceCleanup() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300240 val channel = ArrayChannel<Int>(1)
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300241 val n = 1000
Roman Elizarov1216e912017-02-22 09:57:06 +0300242 expect(1)
243 repeat(n) { i ->
244 select {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300245 channel.onReceive { expectUnreached() }
Roman Elizarov1216e912017-02-22 09:57:06 +0300246 default { expect(i + 2) }
247 }
248 }
249 finish(n + 2)
250 }
251
252 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300253 fun testSelectReceiveDispatchNonSuspending() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300254 val channel = ArrayChannel<Int>(1)
255 expect(1)
256 channel.send(42)
257 expect(2)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300258 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300259 expect(4)
260 select<Unit> {
261 channel.onReceive { v ->
262 expect(5)
263 assertEquals(42, v)
264 expect(6)
265 }
266 }
267 expect(7) // returns from select without further dispatch
268 }
269 expect(3)
270 yield() // to launched
271 finish(8)
272 }
273
274 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300275 fun testSelectReceiveDispatchNonSuspending2() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300276 val channel = ArrayChannel<Int>(1)
277 expect(1)
278 channel.send(42)
279 expect(2)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300280 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300281 expect(4)
282 select<Unit> {
283 channel.onReceive { v ->
284 expect(5)
285 assertEquals(42, v)
286 expect(6)
287 yield() // back to main
288 expect(8)
289 }
290 }
291 expect(9) // returns from select without further dispatch
292 }
293 expect(3)
294 yield() // to launched
295 expect(7)
296 yield() // again
297 finish(10)
298 }
299
300 // only for debugging
301 internal fun <R> SelectBuilder<R>.default(block: suspend () -> R) {
302 this as SelectBuilderImpl // type assertion
303 if (!trySelect(null)) return
Roman Elizarov4638d792017-03-14 19:39:26 +0300304 block.startCoroutineUndispatched(this)
Roman Elizarov1216e912017-02-22 09:57:06 +0300305 }
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300306}