@file:OptIn(DelicateCoroutinesApi::class) package kotlinx.coroutines.channels import kotlinx.coroutines.testing.* import kotlinx.coroutines.* import kotlin.test.* class ConsumeTest: TestBase() { /** Check that [ReceiveChannel.consume] does not suffer from KT-58685 */ @Test fun testConsumeJsMiscompilation() = runTest { val channel = Channel() assertFailsWith { try { channel.consume { null } ?: throw IndexOutOfBoundsException() // should throw… } catch (e: Exception) { throw e // …but instead fails here } } } /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */ @Test fun testConsumeClosesOnSuccess() = runTest { val channel = Channel() channel.consume { } assertTrue(channel.isClosedForReceive) } /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */ @Test fun testConsumeClosesOnFailure() = runTest { val channel = Channel() try { channel.consume { throw TestException() } } catch (e: TestException) { // Expected } assertTrue(channel.isClosedForReceive) } /** Checks that [ReceiveChannel.consume] closes the channel when the block does an early return. */ @Test fun testConsumeClosesOnEarlyReturn() = runTest { val channel = Channel() fun f() { try { channel.consume { return } } catch (e: TestException) { // Expected } } f() assertTrue(channel.isClosedForReceive) } /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */ @Test fun testConsumeEachClosesOnSuccess() = runTest { val channel = Channel(Channel.UNLIMITED) launch { channel.close() } channel.consumeEach { fail("unreached") } assertTrue(channel.isClosedForReceive) } /** Checks that [ReceiveChannel.consume] closes the channel when the block executes successfully. */ @Test fun testConsumeEachClosesOnFailure() = runTest { val channel = Channel(Channel.UNLIMITED) channel.send(Unit) try { channel.consumeEach { throw TestException() } } catch (e: TestException) { // Expected } assertTrue(channel.isClosedForReceive) } /** Checks that [ReceiveChannel.consume] closes the channel when the block does an early return. */ @Test fun testConsumeEachClosesOnEarlyReturn() = runTest { val channel = Channel(Channel.UNLIMITED) channel.send(Unit) suspend fun f() { channel.consumeEach { return@f } } f() assertTrue(channel.isClosedForReceive) } /** Check that [BroadcastChannel.consume] does not suffer from KT-58685 */ @Suppress("DEPRECATION", "DEPRECATION_ERROR") @Test fun testBroadcastChannelConsumeJsMiscompilation() = runTest { val channel = BroadcastChannel(1) assertFailsWith { try { channel.consume { null } ?: throw IndexOutOfBoundsException() // should throw… } catch (e: Exception) { throw e // …but instead fails here } } } }