Skip to content

Commit

Permalink
Update ChannelManager.kt (#637)
Browse files Browse the repository at this point in the history
* Update ChannelManager.kt

Signed-off-by: Luki <[email protected]>

* adding test

Signed-off-by: Luki <[email protected]>

* Update StoreChannelManagerTests.kt

Minor changes for readability, consistency, and scope management

* Update build.gradle.kts

Using Turbine

---------

Signed-off-by: Luki <[email protected]>
Co-authored-by: Matt Ramotar <[email protected]>
  • Loading branch information
lukisk and matt-ramotar authored Jun 1, 2024
1 parent 63928aa commit cc39941
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
10 changes: 10 additions & 0 deletions multicast/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ kotlin {
implementation(libs.kotlinx.coroutines.core)
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(libs.junit)
implementation(libs.kotlinx.coroutines.test)
implementation(libs.turbine)
}
}

val jvmMain by getting
val androidMain by getting
val nativeMain by creating {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.flow.Flow
import org.mobilenativefoundation.store.multicast5.ChannelManager.Message
import kotlin.coroutines.cancellation.CancellationException

internal interface ChannelManager<T> {

Expand Down Expand Up @@ -55,7 +56,11 @@ internal interface ChannelManager<T> {

suspend fun dispatchValue(value: Message.Dispatch.Value<T>) {
_awaitsDispatch = false
channel.send(value)
try {
channel.send(value)
} catch (e: CancellationException) {
// ignore
}
}

fun dispatchError(error: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.mobilenativefoundation.store.multicast5


import app.cash.turbine.test
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals

class StoreChannelManagerTests {

@Test
fun cancelledDownstreamChannelShouldNotCancelOtherChannels() = runTest {
val coroutineScope = CoroutineScope(Dispatchers.Default)
val lockUpstream = Mutex(true)
val testMessages = listOf(1, 2, 3)
val numChannels = 20
val upstreamFlow = flow {
lockUpstream.withLock {
testMessages.onEach { emit(it) }
}
}
val channelManager = StoreChannelManager(
scope = coroutineScope,
bufferSize = 0,
upstream = upstreamFlow,
piggybackingDownstream = false,
keepUpstreamAlive = false,
onEach = { }
)
val channels = createChannels(numChannels)
val channelToBeCancelled = Channel<ChannelManager.Message.Dispatch<Int>>(Channel.UNLIMITED)
.also { channel ->
coroutineScope.launch {
channel.consumeAsFlow().test {
cancelAndIgnoreRemainingEvents()
}
}
}
coroutineScope.launch {
channels.forEach { channelManager.addDownstream(it) }
lockUpstream.unlock()
}
coroutineScope.launch {
channelManager.addDownstream(channelToBeCancelled)
}

channels.forEach { channel ->
val messagesFlow = channel.consumeAsFlow()
.filterIsInstance<ChannelManager.Message.Dispatch.Value<Int>>()
.onEach { it.delivered.complete(Unit) }

messagesFlow.test {
for (message in testMessages) {
val dispatchValue = awaitItem()
assertEquals(message, dispatchValue.value)
}
awaitComplete()
}
}
}

private fun createChannels(count: Int): List<Channel<ChannelManager.Message.Dispatch<Int>>> {
return (1..count).map { Channel(Channel.UNLIMITED) }
}
}

0 comments on commit cc39941

Please sign in to comment.