blob: a0ef4d1bedaed635b3d874c659ad0e85904ababc [file] [log] [blame]
Roman Elizarov187eace2017-01-31 09:39:58 +03001package kotlinx.coroutines.experimental.channels
2
3import kotlinx.coroutines.experimental.*
4import org.junit.Test
5import kotlin.test.assertEquals
6import kotlin.test.assertFalse
7import kotlin.test.assertTrue
8
9class RendezvousChannelTest : TestBase() {
10 @Test
11 fun testSimple() = runBlocking {
12 val q = RendezvousChannel<Int>()
13 check(q.isEmpty && q.isFull)
14 expect(1)
15 val sender = launch(context) {
16 expect(4)
17 q.send(1) // suspend -- the first to come to rendezvous
18 expect(7)
19 q.send(2) // does not suspend -- receiver is there
20 expect(8)
21 }
22 expect(2)
23 val receiver = launch(context) {
24 expect(5)
25 check(q.receive() == 1) // does not suspend -- sender was there
26 expect(6)
27 check(q.receive() == 2) // suspends
28 expect(9)
29 }
30 expect(3)
31 sender.join()
32 receiver.join()
33 check(q.isEmpty && q.isFull)
34 finish(10)
35 }
36
37 @Test
38 fun testStress() = runBlocking {
39 val n = 100_000
40 val q = RendezvousChannel<Int>()
41 val sender = launch(context) {
42 for (i in 1..n) q.send(i)
43 expect(2)
44 }
45 val receiver = launch(context) {
46 for (i in 1..n) check(q.receive() == i)
47 expect(3)
48 }
49 expect(1)
50 sender.join()
51 receiver.join()
52 finish(4)
53 }
54
55 @Test
56 fun testClosedReceiveOrNull() = runBlocking {
57 val q = RendezvousChannel<Int>()
58 check(q.isEmpty && q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
59 expect(1)
60 launch(context) {
61 expect(3)
62 assertEquals(42, q.receiveOrNull())
63 expect(4)
64 assertEquals(null, q.receiveOrNull())
65 expect(6)
66 }
67 expect(2)
68 q.send(42)
69 expect(5)
70 q.close()
71 check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
72 yield()
73 check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
74 finish(7)
75 }
76
77 @Test
78 fun testClosedExceptions() = runBlocking {
79 val q = RendezvousChannel<Int>()
80 expect(1)
81 launch(context) {
82 expect(4)
83 try { q.receive() }
84 catch (e: ClosedReceiveChannelException) {
85 expect(5)
86 }
87 }
88 expect(2)
89 q.close()
90 expect(3)
91 yield()
92 expect(6)
93 try { q.send(42) }
94 catch (e: ClosedSendChannelException) {
95 finish(7)
96 }
97 }
98
99 @Test
100 fun testOfferAndPool() = runBlocking {
101 val q = RendezvousChannel<Int>()
102 assertFalse(q.offer(1))
103 expect(1)
104 launch(context) {
105 expect(3)
Roman Elizarov7b2d8b02017-02-02 20:09:14 +0300106 assertEquals(null, q.poll())
Roman Elizarov187eace2017-01-31 09:39:58 +0300107 expect(4)
108 assertEquals(2, q.receive())
109 expect(7)
Roman Elizarov7b2d8b02017-02-02 20:09:14 +0300110 assertEquals(null, q.poll())
Roman Elizarov187eace2017-01-31 09:39:58 +0300111 yield()
112 expect(9)
Roman Elizarov7b2d8b02017-02-02 20:09:14 +0300113 assertEquals(3, q.poll())
Roman Elizarov187eace2017-01-31 09:39:58 +0300114 expect(10)
115 }
116 expect(2)
117 yield()
118 expect(5)
119 assertTrue(q.offer(2))
120 expect(6)
121 yield()
122 expect(8)
123 q.send(3)
124 finish(11)
125 }
Roman Elizarov7b2d8b02017-02-02 20:09:14 +0300126
127 @Test
128 fun testIteratorClosed() = runBlocking {
129 val q = RendezvousChannel<Int>()
130 expect(1)
131 launch(context) {
132 expect(3)
133 q.close()
134 expect(4)
135 }
136 expect(2)
137 for (x in q) {
138 expectUnreached()
139 }
140 finish(5)
141 }
142
143 @Test
144 fun testIteratorOne() = runBlocking {
145 val q = RendezvousChannel<Int>()
146 expect(1)
147 launch(context) {
148 expect(3)
149 q.send(1)
150 expect(4)
151 q.close()
152 expect(5)
153 }
154 expect(2)
155 for (x in q) {
156 expect(6)
157 assertEquals(1, x)
158 }
159 finish(7)
160 }
161
162 @Test
163 fun testIteratorOneWithYield() = runBlocking {
164 val q = RendezvousChannel<Int>()
165 expect(1)
166 launch(context) {
167 expect(3)
168 q.send(1) // will suspend
169 expect(6)
170 q.close()
171 expect(7)
172 }
173 expect(2)
174 yield() // yield to sender coroutine right before starting for loop
175 expect(4)
176 for (x in q) {
177 expect(5)
178 assertEquals(1, x)
179 }
180 finish(8)
181 }
182
183 @Test
184 fun testIteratorTwo() = runBlocking {
185 val q = RendezvousChannel<Int>()
186 expect(1)
187 launch(context) {
188 expect(3)
189 q.send(1)
190 expect(4)
191 q.send(2)
192 expect(7)
193 q.close()
194 expect(8)
195 }
196 expect(2)
197 for (x in q) {
198 when (x) {
199 1 -> expect(5)
200 2 -> expect(6)
201 else -> expectUnreached()
202 }
203 }
204 finish(9)
205 }
206
207 @Test
208 fun testIteratorTwoWithYield() = runBlocking {
209 val q = RendezvousChannel<Int>()
210 expect(1)
211 launch(context) {
212 expect(3)
213 q.send(1) // will suspend
214 expect(6)
215 q.send(2)
216 expect(7)
217 q.close()
218 expect(8)
219 }
220 expect(2)
221 yield() // yield to sender coroutine right before starting for loop
222 expect(4)
223 for (x in q) {
224 when (x) {
225 1 -> expect(5)
226 2 -> expect(9)
227 else -> expectUnreached()
228 }
229 }
230 finish(10)
231 }
Roman Elizarovb6b01252017-02-06 13:17:40 +0300232
233 class BadClass {
234 override fun equals(other: Any?): Boolean = error("equals")
235 override fun hashCode(): Int = error("hashCode")
236 override fun toString(): String = error("toString")
237 }
238
239 @Test
240 fun testDeferBadClass() = runBlocking {
241 val bad = BadClass()
242 val c = buildChannel(context) {
243 expect(1)
244 send(bad)
245 }
246 assertTrue(c.receive() === bad)
247 finish(2)
248 }
Roman Elizarov187eace2017-01-31 09:39:58 +0300249}