blob: d9853e1a1119d76373724ec1e88c043737b3f532 [file] [log] [blame]
Roman Elizarovecda27f2017-04-06 23:06:26 +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 Elizarovecda27f2017-04-06 23:06:26 +03003 */
4
5package kotlinx.coroutines.experimental.channels
6
Roman Elizarov9fe5f462018-02-21 19:05:52 +03007import kotlinx.coroutines.experimental.*
8import org.hamcrest.core.*
9import org.junit.*
10import org.junit.Assert.*
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +030011import org.junit.runner.*
12import org.junit.runners.*
13import java.io.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030014import kotlin.coroutines.experimental.*
Roman Elizarovecda27f2017-04-06 23:06:26 +030015
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030016@RunWith(Parameterized::class)
17class ActorTest(private val capacity: Int) : TestBase() {
18
19 companion object {
20 @Parameterized.Parameters(name = "Capacity: {0}")
21 @JvmStatic
22 fun params(): Collection<Array<Any>> = listOf(0, 1, Channel.UNLIMITED, Channel.CONFLATED).map { arrayOf<Any>(it) }
23 }
24
Roman Elizarovecda27f2017-04-06 23:06:26 +030025 @Test
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030026 fun testEmpty() = runBlocking {
Roman Elizarovecda27f2017-04-06 23:06:26 +030027 expect(1)
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030028 val actor = actor<String>(coroutineContext, capacity) {
Roman Elizarovecda27f2017-04-06 23:06:26 +030029 expect(3)
30 }
Roman Elizarovb555d912017-08-17 21:01:33 +030031 actor as Job // type assertion
Roman Elizarovecda27f2017-04-06 23:06:26 +030032 assertThat(actor.isActive, IsEqual(true))
33 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030034 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030035 expect(2)
36 yield() // to actor code
37 assertThat(actor.isActive, IsEqual(false))
38 assertThat(actor.isCompleted, IsEqual(true))
Roman Elizarovb555d912017-08-17 21:01:33 +030039 assertThat(actor.isClosedForSend, IsEqual(true))
Roman Elizarovecda27f2017-04-06 23:06:26 +030040 finish(4)
41 }
42
43 @Test
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030044 fun testOne() = runBlocking {
Roman Elizarovecda27f2017-04-06 23:06:26 +030045 expect(1)
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030046 val actor = actor<String>(coroutineContext, capacity) {
Roman Elizarovecda27f2017-04-06 23:06:26 +030047 expect(3)
48 assertThat(receive(), IsEqual("OK"))
49 expect(6)
50 }
Roman Elizarovb555d912017-08-17 21:01:33 +030051 actor as Job // type assertion
Roman Elizarovecda27f2017-04-06 23:06:26 +030052 assertThat(actor.isActive, IsEqual(true))
53 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030054 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030055 expect(2)
56 yield() // to actor code
57 assertThat(actor.isActive, IsEqual(true))
58 assertThat(actor.isCompleted, IsEqual(false))
Roman Elizarovb555d912017-08-17 21:01:33 +030059 assertThat(actor.isClosedForSend, IsEqual(false))
Roman Elizarovecda27f2017-04-06 23:06:26 +030060 expect(4)
61 // send message to actor
62 actor.send("OK")
63 expect(5)
64 yield() // to actor code
65 assertThat(actor.isActive, IsEqual(false))
66 assertThat(actor.isCompleted, IsEqual(true))
Roman Elizarovb555d912017-08-17 21:01:33 +030067 assertThat(actor.isClosedForSend, IsEqual(true))
Roman Elizarovecda27f2017-04-06 23:06:26 +030068 finish(7)
69 }
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030070
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030071 @Test
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +030072 fun testCloseWithoutCause() = runTest {
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030073 val actor = actor<Int>(coroutineContext, capacity) {
74 val element = channel.receiveOrNull()
75 expect(2)
76 assertEquals(42, element)
77 val next = channel.receiveOrNull()
78 assertNull(next)
79 expect(3)
80 }
81
82 expect(1)
83 actor.send(42)
84 yield()
85 actor.close()
86 yield()
87 finish(4)
88 }
89
90 @Test
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +030091 fun testCloseWithCause() = runTest {
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030092 val actor = actor<Int>(coroutineContext, capacity) {
93 val element = channel.receiveOrNull()
94 expect(2)
95 require(element!! == 42)
96 try {
Vsevolod Tolstopyatov87f2faa2018-04-30 22:53:02 +030097 channel.receiveOrNull()
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +030098 } catch (e: IOException) {
99 expect(3)
100 }
101 }
102
103 expect(1)
104 actor.send(42)
105 yield()
106 actor.close(IOException())
107 yield()
108 finish(4)
109 }
Vsevolod Tolstopyatovf5e63ca2018-04-12 19:59:56 +0300110
111 @Test
112 fun testCancelEnclosingJob() = runTest {
113 val job = async(coroutineContext) {
114 actor<Int>(coroutineContext, capacity) {
115 expect(1)
116 channel.receiveOrNull()
117 expectUnreached()
118 }
119 }
120
121 yield()
122 yield()
123
124 expect(2)
125 yield()
126 job.cancel()
127
128 try {
129 job.await()
130 expectUnreached()
131 } catch (e: JobCancellationException) {
132 assertTrue(e.message?.contains("Job was cancelled normally") ?: false)
133 }
134
135 finish(3)
136 }
Vsevolod Tolstopyatovfd424422018-05-23 18:48:37 +0300137
138 @Test
139 fun testThrowingActor() = runTest(unhandled = listOf({e -> e is IllegalArgumentException})) {
140 val parent = Job()
141 val actor = actor<Int>(context = coroutineContext, parent = parent) {
142 channel.consumeEach {
143 expect(1)
144 throw IllegalArgumentException()
145 }
146 }
147
148 actor.send(1)
149 parent.cancel()
150 parent.join()
151 finish(2)
152 }
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300153}