blob: d4a9be4fdbcfac1b4e15fa669ddfa39c3e8e0107 [file] [log] [blame]
Roman Elizarov1216e912017-02-22 09:57:06 +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 Elizarov1216e912017-02-22 09:57:06 +03003 */
4
5package kotlinx.coroutines.experimental.selects
6
Roman Elizarov9fe5f462018-02-21 19:05:52 +03007import kotlinx.coroutines.experimental.*
8import kotlinx.coroutines.experimental.channels.*
9import kotlinx.coroutines.experimental.intrinsics.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030010import kotlin.coroutines.experimental.*
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030011import kotlin.test.*
Roman Elizarov1216e912017-02-22 09:57:06 +030012
13class SelectArrayChannelTest : TestBase() {
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030014
Roman Elizarov1216e912017-02-22 09:57:06 +030015 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030016 fun testSelectSendSuccess() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030017 expect(1)
18 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030019 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030020 expect(2)
21 assertEquals("OK", channel.receive())
22 finish(6)
23 }
24 yield() // to launched coroutine
25 expect(3)
26 select<Unit> {
27 channel.onSend("OK") {
28 expect(4)
29 }
30 }
31 expect(5)
32 }
33
34 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030035 fun testSelectSendSuccessWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030036 expect(1)
37 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030038 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030039 expect(2)
40 assertEquals("OK", channel.receive())
41 finish(6)
42 }
43 yield() // to launched coroutine
44 expect(3)
45 select<Unit> {
46 channel.onSend("OK") {
47 expect(4)
48 }
49 default {
50 expectUnreached()
51 }
52 }
53 expect(5)
54 }
55
56 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030057 fun testSelectSendReceiveBuf() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030058 expect(1)
59 val channel = ArrayChannel<String>(1)
60 select<Unit> {
61 channel.onSend("OK") {
62 expect(2)
63 }
64 }
65 expect(3)
66 select<Unit> {
67 channel.onReceive { v ->
68 expect(4)
69 assertEquals("OK", v)
70 }
71 }
72 finish(5)
73 }
74
75 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030076 fun testSelectSendWait() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030077 expect(1)
78 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030079 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +030080 expect(4)
81 assertEquals("BUF", channel.receive())
82 expect(5)
83 assertEquals("OK", channel.receive())
84 expect(6)
85 }
86 expect(2)
87 channel.send("BUF")
88 expect(3)
89 select<Unit> {
90 channel.onSend("OK") {
91 expect(7)
92 }
93 }
94 finish(8)
95 }
96
97 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +030098 fun testSelectReceiveSuccess() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +030099 expect(1)
100 val channel = ArrayChannel<String>(1)
101 channel.send("OK")
102 expect(2)
103 select<Unit> {
104 channel.onReceive { v ->
105 expect(3)
106 assertEquals("OK", v)
107 }
108 }
109 finish(4)
110 }
111
112 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300113 fun testSelectReceiveSuccessWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300114 expect(1)
115 val channel = ArrayChannel<String>(1)
116 channel.send("OK")
117 expect(2)
118 select<Unit> {
119 channel.onReceive { v ->
120 expect(3)
121 assertEquals("OK", v)
122 }
123 default {
124 expectUnreached()
125 }
126 }
127 finish(4)
128 }
129
130 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300131 fun testSelectReceiveWaitWithDefault() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300132 expect(1)
133 val channel = ArrayChannel<String>(1)
134 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300135 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300136 expectUnreached()
137 }
138 default {
139 expect(2)
140 }
141 }
142 expect(3)
143 channel.send("BUF")
144 expect(4)
145 // make sure second send blocks (select above is over)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300146 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300147 expect(6)
148 channel.send("CHK")
149 finish(10)
150 }
151 expect(5)
152 yield()
153 expect(7)
154 assertEquals("BUF", channel.receive())
155 expect(8)
156 assertEquals("CHK", channel.receive())
157 expect(9)
158 }
159
160 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300161 fun testSelectReceiveWait() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300162 expect(1)
163 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300164 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300165 expect(3)
166 channel.send("OK")
167 expect(4)
168 }
169 expect(2)
170 select<Unit> {
171 channel.onReceive { v ->
172 expect(5)
173 assertEquals("OK", v)
174 }
175 }
176 finish(6)
177 }
178
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300179 @Test
180 fun testSelectReceiveClosed() = runTest({it is ClosedReceiveChannelException}) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300181 expect(1)
182 val channel = ArrayChannel<String>(1)
183 channel.close()
184 finish(2)
185 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300186 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300187 expectUnreached()
188 }
189 }
190 expectUnreached()
191 }
192
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300193 @Test
194 fun testSelectReceiveWaitClosed() = runTest({it is ClosedReceiveChannelException}) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300195 expect(1)
196 val channel = ArrayChannel<String>(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300197 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300198 expect(3)
199 channel.close()
200 finish(4)
201 }
202 expect(2)
203 select<Unit> {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300204 channel.onReceive {
Roman Elizarov1216e912017-02-22 09:57:06 +0300205 expectUnreached()
206 }
207 }
208 expectUnreached()
209 }
210
211 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300212 fun testSelectSendResourceCleanup() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300213 val channel = ArrayChannel<Int>(1)
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300214 val n = 1000
Roman Elizarov1216e912017-02-22 09:57:06 +0300215 expect(1)
216 channel.send(-1) // fill the buffer, so all subsequent sends cannot proceed
217 repeat(n) { i ->
218 select {
219 channel.onSend(i) { expectUnreached() }
220 default { expect(i + 2) }
221 }
222 }
223 finish(n + 2)
224 }
225
226 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300227 fun testSelectReceiveResourceCleanup() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300228 val channel = ArrayChannel<Int>(1)
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300229 val n = 1000
Roman Elizarov1216e912017-02-22 09:57:06 +0300230 expect(1)
231 repeat(n) { i ->
232 select {
Roman Elizarov7adb8762017-03-17 17:54:13 +0300233 channel.onReceive { expectUnreached() }
Roman Elizarov1216e912017-02-22 09:57:06 +0300234 default { expect(i + 2) }
235 }
236 }
237 finish(n + 2)
238 }
239
240 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300241 fun testSelectReceiveDispatchNonSuspending() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300242 val channel = ArrayChannel<Int>(1)
243 expect(1)
244 channel.send(42)
245 expect(2)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300246 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300247 expect(4)
248 select<Unit> {
249 channel.onReceive { v ->
250 expect(5)
251 assertEquals(42, v)
252 expect(6)
253 }
254 }
255 expect(7) // returns from select without further dispatch
256 }
257 expect(3)
258 yield() // to launched
259 finish(8)
260 }
261
262 @Test
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300263 fun testSelectReceiveDispatchNonSuspending2() = runTest {
Roman Elizarov1216e912017-02-22 09:57:06 +0300264 val channel = ArrayChannel<Int>(1)
265 expect(1)
266 channel.send(42)
267 expect(2)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300268 launch(coroutineContext) {
Roman Elizarov1216e912017-02-22 09:57:06 +0300269 expect(4)
270 select<Unit> {
271 channel.onReceive { v ->
272 expect(5)
273 assertEquals(42, v)
274 expect(6)
275 yield() // back to main
276 expect(8)
277 }
278 }
279 expect(9) // returns from select without further dispatch
280 }
281 expect(3)
282 yield() // to launched
283 expect(7)
284 yield() // again
285 finish(10)
286 }
287
288 // only for debugging
289 internal fun <R> SelectBuilder<R>.default(block: suspend () -> R) {
290 this as SelectBuilderImpl // type assertion
291 if (!trySelect(null)) return
Roman Elizarov4638d792017-03-14 19:39:26 +0300292 block.startCoroutineUndispatched(this)
Roman Elizarov1216e912017-02-22 09:57:06 +0300293 }
Vsevolod Tolstopyatov2cdbfd72018-04-22 18:26:14 +0300294}