Skip to content

Commit 5471a44

Browse files
authored
Add tests for Channel closed with an exception (#4517)
1 parent d1c583a commit 5471a44

File tree

3 files changed

+93
-11
lines changed

3 files changed

+93
-11
lines changed

kotlinx-coroutines-core/common/test/channels/BasicOperationsTest.kt

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,31 @@ class BasicOperationsTest : TestBase() {
88
@Test
99
fun testSimpleSendReceive() = runTest {
1010
// Parametrized common test :(
11-
TestChannelKind.values().forEach { kind -> testSendReceive(kind, 20) }
11+
TestChannelKind.entries.forEach { kind -> testSendReceive(kind, 20) }
1212
}
1313

1414
@Test
1515
fun testTrySendToFullChannel() = runTest {
16-
TestChannelKind.values().forEach { kind -> testTrySendToFullChannel(kind) }
16+
TestChannelKind.entries.forEach { kind -> testTrySendToFullChannel(kind) }
1717
}
1818

1919
@Test
2020
fun testTrySendAfterClose() = runTest {
21-
TestChannelKind.values().forEach { kind -> testTrySendAfterClose(kind) }
21+
TestChannelKind.entries.forEach { kind -> testTrySendAfterClose(kind) }
2222
}
2323

2424
@Test
2525
fun testSendAfterClose() = runTest {
26-
TestChannelKind.values().forEach { kind -> testSendAfterClose(kind) }
26+
TestChannelKind.entries.forEach { kind -> testSendAfterClose(kind) }
2727
}
2828

2929
@Test
3030
fun testReceiveCatching() = runTest {
31-
TestChannelKind.values().forEach { kind -> testReceiveCatching(kind) }
31+
TestChannelKind.entries.forEach { kind -> testReceiveCatching(kind) }
3232
}
3333

3434
@Test
35-
fun testInvokeOnClose() = TestChannelKind.values().forEach { kind ->
35+
fun testInvokeOnClose() = TestChannelKind.entries.forEach { kind ->
3636
reset()
3737
val channel = kind.create<Int>()
3838
channel.invokeOnClose {
@@ -48,7 +48,7 @@ class BasicOperationsTest : TestBase() {
4848
}
4949

5050
@Test
51-
fun testInvokeOnClosed() = TestChannelKind.values().forEach { kind ->
51+
fun testInvokeOnClosed() = TestChannelKind.entries.forEach { kind ->
5252
reset()
5353
expect(1)
5454
val channel = kind.create<Int>()
@@ -59,7 +59,7 @@ class BasicOperationsTest : TestBase() {
5959
}
6060

6161
@Test
62-
fun testMultipleInvokeOnClose() = TestChannelKind.values().forEach { kind ->
62+
fun testMultipleInvokeOnClose() = TestChannelKind.entries.forEach { kind ->
6363
reset()
6464
val channel = kind.create<Int>()
6565
channel.invokeOnClose { expect(3) }
@@ -71,14 +71,16 @@ class BasicOperationsTest : TestBase() {
7171
}
7272

7373
@Test
74-
fun testIterator() = runTest {
75-
TestChannelKind.values().forEach { kind ->
74+
fun testIteratorHasNextMustPrecedeNext() = runTest {
75+
TestChannelKind.entries.forEach { kind ->
7676
val channel = kind.create<Int>()
7777
val iterator = channel.iterator()
7878
assertFailsWith<IllegalStateException> { iterator.next() }
7979
channel.close()
8080
assertFailsWith<IllegalStateException> { iterator.next() }
8181
assertFalse(iterator.hasNext())
82+
assertFailsWith<NoSuchElementException> { iterator.next() }
83+
assertFailsWith<IllegalStateException> { iterator.next() }
8284
}
8385
}
8486

@@ -109,7 +111,7 @@ class BasicOperationsTest : TestBase() {
109111
try {
110112
expect(2)
111113
channel.close()
112-
} catch (e: TestException) {
114+
} catch (_: TestException) {
113115
expect(4)
114116
}
115117
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package kotlinx.coroutines.channels
2+
3+
import kotlinx.coroutines.testing.*
4+
import kotlin.test.*
5+
6+
class ChannelIteratorTest : TestBase() {
7+
@Test
8+
fun testIteratorClosedHasNextFalse() = runTest {
9+
TestChannelKind.entries.forEach { kind ->
10+
val channel = kind.create<Int>()
11+
val iterator = channel.iterator()
12+
channel.close()
13+
assertFalse(iterator.hasNext())
14+
}
15+
}
16+
17+
@Test
18+
fun testIteratorClosedWithExceptionHasNextThrows() = runTest {
19+
TestChannelKind.entries.forEach { kind ->
20+
val channel = kind.create<Int>()
21+
val iterator = channel.iterator()
22+
channel.close(TestException())
23+
assertFailsWith<TestException> { iterator.hasNext() }
24+
}
25+
}
26+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package kotlinx.coroutines.channels
2+
3+
import kotlinx.coroutines.testing.*
4+
import kotlin.test.*
5+
6+
/**
7+
* Properties stay the same regardless of whether the channel was closed with or without exception.
8+
*/
9+
class ChannelPropertiesAfterClosingTest : TestBase() {
10+
@Test
11+
fun testClosedIsClosedForReceive() = runTest {
12+
TestChannelKind.entries.forEach { kind ->
13+
for (exception in listOf(null, TestException())) {
14+
val channel = kind.create<Int>()
15+
assertFalse(channel.isClosedForReceive)
16+
channel.close(exception)
17+
assertTrue(channel.isClosedForReceive)
18+
}
19+
}
20+
}
21+
22+
@Test
23+
fun testClosedIsEmptyFalse() = runTest {
24+
TestChannelKind.entries.forEach { kind ->
25+
for (exception in listOf(null, TestException())) {
26+
val channel = kind.create<Int>()
27+
assertTrue(channel.isEmpty)
28+
assertFalse(channel.isClosedForReceive)
29+
channel.close(exception)
30+
// NB! Not obvious.
31+
assertFalse(channel.isEmpty)
32+
assertTrue(channel.isClosedForReceive)
33+
}
34+
}
35+
}
36+
37+
@Test
38+
fun testSendClosedReceiveIsEmptyFalse() = runTest {
39+
for (exception in listOf(null, TestException())) {
40+
val channel = Channel<Int>(1)
41+
assertTrue(channel.isEmpty)
42+
assertFalse(channel.isClosedForReceive)
43+
channel.send(1)
44+
assertFalse(channel.isEmpty)
45+
assertFalse(channel.isClosedForReceive)
46+
channel.close(exception)
47+
assertFalse(channel.isEmpty)
48+
assertFalse(channel.isClosedForReceive)
49+
channel.receive()
50+
assertFalse(channel.isEmpty)
51+
assertTrue(channel.isClosedForReceive)
52+
}
53+
}
54+
}

0 commit comments

Comments
 (0)