Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Channel.receiveOrNull becomes extension, internal receiveOrClosed added
* The corresponding ReceiveChannel methods are deprecated. * Introduced corresponding extensions with the same semantic and generic Any bound. * Introduce internal ReceiveChannel.[on]receiveOrClosed * Using internal inline class ValueOrClosed. * To be stabilized and made public in the future when inline classes ABI stabilizes. * It is related to #330 but does not resolve it yet. * Includes todos for future public ValueOrClose design. * Simplify AbstractChannel select implementations. * AbstractChannel implementation is optimized to avoid code duplication in suspension of different receive methods: receive, receiveOrNull, receiveOrClosed.
- Loading branch information
Showing
15 changed files
with
760 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
common/kotlinx-coroutines-core-common/test/channels/ChannelReceiveOrClosedTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/* | ||
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.coroutines.channels | ||
|
||
import kotlinx.coroutines.* | ||
import kotlin.test.* | ||
|
||
class ChannelReceiveOrClosedTest : TestBase() { | ||
@Test | ||
fun testChannelOfThrowables() = runTest { | ||
val channel = Channel<Throwable>() | ||
launch { | ||
channel.send(TestException1()) | ||
channel.close(TestException2()) | ||
} | ||
|
||
val element = channel.receiveOrClosed() | ||
assertTrue(element.isValue) | ||
assertTrue(element.value is TestException1) | ||
assertTrue(element.valueOrNull is TestException1) | ||
|
||
val closed = channel.receiveOrClosed() | ||
assertTrue(closed.isClosed) | ||
assertTrue(closed.closeCause is TestException2) | ||
} | ||
|
||
@Test | ||
@Suppress("ReplaceAssertBooleanWithAssertEquality") // inline classes test | ||
fun testNullableIntChanel() = runTest { | ||
val channel = Channel<Int?>() | ||
launch { | ||
expect(2) | ||
channel.send(1) | ||
expect(3) | ||
channel.send(null) | ||
|
||
expect(6) | ||
channel.close() | ||
} | ||
|
||
expect(1) | ||
val element = channel.receiveOrClosed() | ||
assertTrue(element.isValue) | ||
assertEquals(1, element.value) | ||
assertEquals(1, element.valueOrNull) | ||
assertEquals("Value(1)", element.toString()) | ||
assertTrue(ValueOrClosed.value(1) == element) // Don't box | ||
|
||
expect(4) | ||
val nullElement = channel.receiveOrClosed() | ||
assertTrue(nullElement.isValue) | ||
assertNull(nullElement.value) | ||
assertNull(nullElement.valueOrNull) | ||
assertEquals("Value(null)", nullElement.toString()) | ||
assertTrue(ValueOrClosed.value(null) == nullElement) // Don't box | ||
|
||
expect(5) | ||
val closed = channel.receiveOrClosed() | ||
assertTrue(closed.isClosed) | ||
|
||
val closed2 = channel.receiveOrClosed() | ||
assertTrue(closed2.isClosed) | ||
assertTrue(closed2.closeCause is ClosedReceiveChannelException) | ||
finish(7) | ||
} | ||
|
||
@Test | ||
@ExperimentalUnsignedTypes | ||
fun testUIntChannel() = runTest { | ||
val channel = Channel<UInt>() | ||
launch { | ||
expect(2) | ||
channel.send(1u) | ||
yield() | ||
expect(4) | ||
channel.send((Long.MAX_VALUE - 1).toUInt()) | ||
expect(5) | ||
} | ||
|
||
expect(1) | ||
val element = channel.receiveOrClosed() | ||
assertEquals(1u, element.value) | ||
|
||
expect(3) | ||
val element2 = channel.receiveOrClosed() | ||
assertEquals((Long.MAX_VALUE - 1).toUInt(), element2.value) | ||
finish(6) | ||
} | ||
|
||
@Test | ||
fun testCancelChannel() = runTest { | ||
val channel = Channel<Boolean>() | ||
launch { | ||
expect(2) | ||
channel.cancel() | ||
} | ||
|
||
expect(1) | ||
val closed = channel.receiveOrClosed() | ||
assertTrue(closed.isClosed) | ||
assertTrue(closed.closeCause is ClosedReceiveChannelException) | ||
finish(3) | ||
} | ||
|
||
@Test | ||
@ExperimentalUnsignedTypes | ||
fun testReceiveResultChannel() = runTest { | ||
val channel = Channel<ValueOrClosed<UInt>>() | ||
launch { | ||
channel.send(ValueOrClosed.value(1u)) | ||
channel.send(ValueOrClosed.closed(TestException1())) | ||
channel.close(TestException2()) | ||
} | ||
|
||
val intResult = channel.receiveOrClosed() | ||
assertTrue(intResult.isValue) | ||
assertEquals(1u, intResult.value.value) | ||
|
||
val closeCauseResult = channel.receiveOrClosed() | ||
assertTrue(closeCauseResult.isValue) | ||
assertTrue(closeCauseResult.value.closeCause is TestException1) | ||
|
||
val closeCause = channel.receiveOrClosed() | ||
assertTrue(closeCause.isClosed) | ||
assertTrue(closeCause.closeCause is TestException2) | ||
assertFailsWith<TestException2> { closeCause.valueOrThrow } | ||
} | ||
|
||
@Test | ||
fun testToString() = runTest { | ||
val channel = Channel<String>(1) | ||
channel.send("message") | ||
channel.close(TestException1()) | ||
assertEquals("Value(message)", channel.receiveOrClosed().toString()) | ||
// toString implementation for exception differs on every platform | ||
val str = channel.receiveOrClosed().toString() | ||
assertTrue(str.matches("Closed\\(.*TestException1\\)".toRegex())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.