blob: 13572557f961d0f01ab7785d2d5e55ce80060437 [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +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 Elizarovf16fd272017-02-07 11:26:00 +03003 */
4
Roman Elizarov7b2d8b02017-02-02 20:09:14 +03005package kotlinx.coroutines.experimental.channels
6
7import kotlinx.coroutines.experimental.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +03008import kotlin.coroutines.experimental.*
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +03009import kotlin.test.*
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030010
11class ArrayChannelTest : TestBase() {
12 @Test
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +030013 fun testSimple() = runTest {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030014 val q = ArrayChannel<Int>(1)
15 check(q.isEmpty && !q.isFull)
16 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030017 val sender = launch(coroutineContext) {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030018 expect(4)
19 q.send(1) // success -- buffered
20 check(!q.isEmpty && q.isFull)
21 expect(5)
22 q.send(2) // suspends (buffer full)
23 expect(9)
24 }
25 expect(2)
Roman Elizarov43e3af72017-07-21 16:01:31 +030026 val receiver = launch(coroutineContext) {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030027 expect(6)
28 check(q.receive() == 1) // does not suspend -- took from buffer
29 check(!q.isEmpty && q.isFull) // waiting sender's element moved to buffer
30 expect(7)
31 check(q.receive() == 2) // does not suspend (takes from sender)
32 expect(8)
33 }
34 expect(3)
35 sender.join()
36 receiver.join()
37 check(q.isEmpty && !q.isFull)
38 finish(10)
39 }
40
41 @Test
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +030042 fun testClosedBufferedReceiveOrNull() = runTest {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030043 val q = ArrayChannel<Int>(1)
44 check(q.isEmpty && !q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
45 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030046 launch(coroutineContext) {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030047 expect(5)
48 check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive)
49 assertEquals(42, q.receiveOrNull())
50 expect(6)
51 check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
52 assertEquals(null, q.receiveOrNull())
53 expect(7)
54 }
55 expect(2)
56 q.send(42) // buffers
57 expect(3)
58 q.close() // goes on
59 expect(4)
60 check(!q.isEmpty && !q.isFull && q.isClosedForSend && !q.isClosedForReceive)
61 yield()
62 check(!q.isEmpty && !q.isFull && q.isClosedForSend && q.isClosedForReceive)
63 finish(8)
64 }
65
66 @Test
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +030067 fun testClosedExceptions() = runTest {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030068 val q = ArrayChannel<Int>(1)
69 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030070 launch(coroutineContext) {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030071 expect(4)
72 try { q.receive() }
73 catch (e: ClosedReceiveChannelException) {
74 expect(5)
75 }
76 }
77 expect(2)
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +030078
79 require(q.close())
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030080 expect(3)
81 yield()
82 expect(6)
83 try { q.send(42) }
84 catch (e: ClosedSendChannelException) {
85 finish(7)
86 }
87 }
88
89 @Test
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +030090 fun testOfferAndPool() = runTest {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030091 val q = ArrayChannel<Int>(1)
92 assertTrue(q.offer(1))
93 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +030094 launch(coroutineContext) {
Roman Elizarov7b2d8b02017-02-02 20:09:14 +030095 expect(3)
96 assertEquals(1, q.poll())
97 expect(4)
98 assertEquals(null, q.poll())
99 expect(5)
100 assertEquals(2, q.receive()) // suspends
101 expect(9)
102 assertEquals(3, q.poll())
103 expect(10)
104 assertEquals(null, q.poll())
105 expect(11)
106 }
107 expect(2)
108 yield()
109 expect(6)
110 assertTrue(q.offer(2))
111 expect(7)
112 assertTrue(q.offer(3))
113 expect(8)
114 assertFalse(q.offer(4))
115 yield()
116 finish(12)
117 }
Roman Elizarovb555d912017-08-17 21:01:33 +0300118
119 @Test
Vsevolod Tolstopyatov96191342018-04-20 18:13:33 +0300120 fun testConsumeAll() = runTest {
Roman Elizarovb555d912017-08-17 21:01:33 +0300121 val q = ArrayChannel<Int>(5)
122 for (i in 1..10) {
123 if (i <= 5) {
124 expect(i)
125 q.send(i) // shall buffer
126 } else {
127 launch(coroutineContext, CoroutineStart.UNDISPATCHED) {
128 expect(i)
129 q.send(i) // suspends
130 expectUnreached() // will get cancelled by cancel
131 }
132 }
133 }
134 expect(11)
135 q.cancel()
136 check(q.isClosedForSend)
137 check(q.isClosedForReceive)
138 check(q.receiveOrNull() == null)
139 finish(12)
140 }
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300141
Roman Elizarovf2bdf602018-04-26 11:29:47 +0300142 @Test
143 fun testCancelWithCause() = runTest({ it is TestException }) {
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300144 val channel = ArrayChannel<Int>(5)
Roman Elizarovf2bdf602018-04-26 11:29:47 +0300145 channel.cancel(TestException())
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300146 channel.receiveOrNull()
147 }
Roman Elizarovf2bdf602018-04-26 11:29:47 +0300148
149 private class TestException : Exception()
Vsevolod Tolstopyatov4b9a5592018-04-11 13:17:14 +0300150}