blob: e789f4d0433aa14243505b045124f3669633435a [file] [log] [blame]
Roman Elizarovecda27f2017-04-06 23:06:26 +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.channels
18
Roman Elizarov9fe5f462018-02-21 19:05:52 +030019import kotlinx.coroutines.experimental.*
20import org.hamcrest.core.*
21import org.junit.*
22import org.junit.Assert.*
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +030023import org.junit.runner.*
24import org.junit.runners.*
25import java.io.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030026import kotlin.coroutines.experimental.*
Roman Elizarovecda27f2017-04-06 23:06:26 +030027
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030028@RunWith(Parameterized::class)
29class ActorTest(private val capacity: Int) : TestBase() {
30
31 companion object {
32 @Parameterized.Parameters(name = "Capacity: {0}")
33 @JvmStatic
34 fun params(): Collection<Array<Any>> = listOf(0, 1, Channel.UNLIMITED, Channel.CONFLATED).map { arrayOf<Any>(it) }
35 }
36
Roman Elizarovecda27f2017-04-06 23:06:26 +030037 @Test
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030038 fun testEmpty() = runBlocking {
Roman Elizarovecda27f2017-04-06 23:06:26 +030039 expect(1)
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030040 val actor = actor<String>(coroutineContext, capacity) {
Roman Elizarovecda27f2017-04-06 23:06:26 +030041 expect(3)
42 }
Roman Elizarovb555d912017-08-17 21:01:33 +030043 actor as Job // type assertion
Roman Elizarovecda27f2017-04-06 23:06:26 +030044 assertThat(actor.isActive, IsEqual(true))
45 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030046 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030047 expect(2)
48 yield() // to actor code
49 assertThat(actor.isActive, IsEqual(false))
50 assertThat(actor.isCompleted, IsEqual(true))
Roman Elizarovb555d912017-08-17 21:01:33 +030051 assertThat(actor.isClosedForSend, IsEqual(true))
Roman Elizarovecda27f2017-04-06 23:06:26 +030052 finish(4)
53 }
54
55 @Test
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030056 fun testOne() = runBlocking {
Roman Elizarovecda27f2017-04-06 23:06:26 +030057 expect(1)
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030058 val actor = actor<String>(coroutineContext, capacity) {
Roman Elizarovecda27f2017-04-06 23:06:26 +030059 expect(3)
60 assertThat(receive(), IsEqual("OK"))
61 expect(6)
62 }
Roman Elizarovb555d912017-08-17 21:01:33 +030063 actor as Job // type assertion
Roman Elizarovecda27f2017-04-06 23:06:26 +030064 assertThat(actor.isActive, IsEqual(true))
65 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030066 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030067 expect(2)
68 yield() // to actor code
69 assertThat(actor.isActive, IsEqual(true))
70 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030071 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030072 expect(4)
73 // send message to actor
74 actor.send("OK")
75 expect(5)
76 yield() // to actor code
77 assertThat(actor.isActive, IsEqual(false))
78 assertThat(actor.isCompleted, IsEqual(true))
Roman Elizarovb555d912017-08-17 21:01:33 +030079 assertThat(actor.isClosedForSend, IsEqual(true))
Roman Elizarovecda27f2017-04-06 23:06:26 +030080 finish(7)
81 }
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030082
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030083 @Test
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +030084 fun testCloseWithoutCause() = runTest {
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030085 val actor = actor<Int>(coroutineContext, capacity) {
86 val element = channel.receiveOrNull()
87 expect(2)
88 assertEquals(42, element)
89 val next = channel.receiveOrNull()
90 assertNull(next)
91 expect(3)
92 }
93
94 expect(1)
95 actor.send(42)
96 yield()
97 actor.close()
98 yield()
99 finish(4)
100 }
101
102 @Test
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +0300103 fun testCloseWithCause() = runTest {
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300104 val actor = actor<Int>(coroutineContext, capacity) {
105 val element = channel.receiveOrNull()
106 expect(2)
107 require(element!! == 42)
108 try {
Vsevolod Tolstopyatov87f2faa2018-04-30 22:53:02 +0300109 channel.receiveOrNull()
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300110 } catch (e: IOException) {
111 expect(3)
112 }
113 }
114
115 expect(1)
116 actor.send(42)
117 yield()
118 actor.close(IOException())
119 yield()
120 finish(4)
121 }
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +0300122
123 @Test
124 fun testCancelEnclosingJob() = runTest {
125 val job = async(coroutineContext) {
126 actor<Int>(coroutineContext, capacity) {
127 expect(1)
128 channel.receiveOrNull()
129 expectUnreached()
130 }
131 }
132
133 yield()
134 yield()
135
136 expect(2)
137 yield()
138 job.cancel()
139
140 try {
141 job.await()
142 expectUnreached()
143 } catch (e: JobCancellationException) {
144 assertTrue(e.message?.contains("Job was cancelled normally") ?: false)
145 }
146
147 finish(3)
148 }
Vsevolod Tolstopyatovfd424422018-05-23 18:48:37 +0300149
150 @Test
151 fun testThrowingActor() = runTest(unhandled = listOf({e -> e is IllegalArgumentException})) {
152 val parent = Job()
153 val actor = actor<Int>(context = coroutineContext, parent = parent) {
154 channel.consumeEach {
155 expect(1)
156 throw IllegalArgumentException()
157 }
158 }
159
160 actor.send(1)
161 parent.cancel()
162 parent.join()
163 finish(2)
164 }
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300165}