Skip to content

Commit 49ca10c

Browse files
committed
test and add KClass to key
1 parent 52e518b commit 49ca10c

File tree

7 files changed

+2120
-9
lines changed

7 files changed

+2120
-9
lines changed

channel-event-bus/build.gradle.kts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,18 @@ kotlin {
6868
implementation(libs.coroutines.test)
6969
}
7070
}
71+
72+
jsTest {
73+
dependencies {
74+
implementation(kotlin("test-js"))
75+
}
76+
}
77+
78+
jvmTest {
79+
dependencies {
80+
implementation(kotlin("test-junit"))
81+
}
82+
}
7183
}
7284

7385
sourceSets.matching { it.name.contains("Test") }.all {
Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
package com.hoc081098.channeleventbus
22

3+
import kotlin.reflect.KClass
4+
35
/**
46
* Represents an event that can be sent to a [ChannelEventBus].
57
*/
6-
public interface ChannelEvent<out T : ChannelEvent<T>> {
7-
public interface Key<
8-
@Suppress("unused")
9-
out T : ChannelEvent<T>,
10-
>
11-
8+
public interface ChannelEvent<T : ChannelEvent<T>> {
129
/**
1310
* The key to identify a bus for this type of events.
1411
*/
1512
public val key: Key<T>
13+
14+
public open class Key<T : ChannelEvent<T>>(public val eventClass: KClass<T>) {
15+
final override fun equals(other: Any?): Boolean {
16+
if (this === other) return true
17+
if (other !is Key<*>) return false
18+
return eventClass == other.eventClass
19+
}
20+
21+
final override fun hashCode(): Int = eventClass.hashCode()
22+
23+
final override fun toString(): String = "ChannelEvent.Key(${eventClass.simpleName})"
24+
}
1625
}
1726

18-
internal typealias ChannelEventKey<T> = ChannelEvent.Key<T>
27+
/**
28+
* Alias for [ChannelEvent.Key].
29+
* @see [ChannelEvent.Key]
30+
*/
31+
public typealias ChannelEventKey<T> = ChannelEvent.Key<T>

channel-event-bus/src/commonMain/kotlin/com/hoc081098/channeleventbus/ChannelEventBus.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import kotlin.collections.component1
44
import kotlin.collections.component2
55
import kotlin.collections.set
66
import kotlin.jvm.JvmField
7+
import kotlin.reflect.cast
78
import kotlinx.coroutines.ExperimentalCoroutinesApi
89
import kotlinx.coroutines.InternalCoroutinesApi
910
import kotlinx.coroutines.channels.Channel
@@ -210,13 +211,12 @@ private class ChannelEventBusImpl(
210211
.trySend(event)
211212
.getOrElse { throw ChannelEventBusException.FailedToSendEvent(event, it) }
212213

213-
@Suppress("UNCHECKED_CAST")
214214
override fun <T : ChannelEvent<T>> receiveAsFlow(key: ChannelEventKey<T>): Flow<T> = flow {
215215
try {
216216
getOrCreateBusAndMarkAsCollecting(key)
217217
.channel
218218
.receiveAsFlow()
219-
.map { it as T }
219+
.map { key.eventClass.cast(it) }
220220
.let { emitAll(it) }
221221
} catch (@Suppress("TooGenericExceptionCaught") e: Throwable) {
222222
markAsNotCollecting(key)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.hoc081098.channeleventbus
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertContentEquals
5+
import kotlinx.coroutines.flow.take
6+
import kotlinx.coroutines.flow.toList
7+
import kotlinx.coroutines.launch
8+
import kotlinx.coroutines.test.runTest
9+
10+
class ChannelEventBusTest {
11+
@Test
12+
fun sendAndReceiveMultiple() = runTest {
13+
val bus = ChannelEventBus(ConsoleChannelEventBusLogger)
14+
15+
val sentTestEventInts = mutableListOf<TestEventInt>()
16+
val sentTestEventStrings = mutableListOf<TestEventString>()
17+
val sentTestEventLongs = mutableListOf<TestEventLong>()
18+
19+
repeat(100 * 3) { i ->
20+
launch {
21+
when (i % 3) {
22+
0 -> bus.send(TestEventInt(i).also { sentTestEventInts += it })
23+
1 -> bus.send(TestEventString(i.toString()).also { sentTestEventStrings += it })
24+
2 -> bus.send(TestEventLong(i.toLong()).also { sentTestEventLongs += it })
25+
else -> error("Unreachable")
26+
}
27+
}
28+
}
29+
30+
launch {
31+
val testEventInts = bus
32+
.receiveAsFlow(TestEventInt)
33+
.take(100)
34+
.toList()
35+
36+
assertContentEquals(
37+
expected = sentTestEventInts,
38+
actual = testEventInts,
39+
)
40+
}
41+
42+
launch {
43+
val testEventStrings = bus
44+
.receiveAsFlow(TestEventString)
45+
.take(100)
46+
.toList()
47+
48+
assertContentEquals(
49+
expected = sentTestEventStrings,
50+
actual = testEventStrings,
51+
)
52+
}
53+
54+
launch {
55+
val testEventStrings = bus
56+
.receiveAsFlow(TestEventLong)
57+
.take(100)
58+
.toList()
59+
60+
assertContentEquals(
61+
expected = sentTestEventLongs,
62+
actual = testEventStrings,
63+
)
64+
}
65+
}
66+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.hoc081098.channeleventbus
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertEquals
5+
6+
class ChannelEventTest {
7+
@Test
8+
fun testKeyEquals() {
9+
assertEquals(TestEventIntKey, TestEventInt)
10+
assertEquals(TestEventStringKey, TestEventString)
11+
assertEquals(TestEventLongKey, TestEventLong)
12+
}
13+
14+
@Test
15+
fun testKeyHashCode() {
16+
assertEquals(TestEventIntKey.hashCode(), TestEventInt.hashCode())
17+
assertEquals(TestEventStringKey.hashCode(), TestEventString.hashCode())
18+
assertEquals(TestEventLongKey.hashCode(), TestEventLong.hashCode())
19+
}
20+
21+
@Test
22+
fun testKeyToString() {
23+
assertEquals("ChannelEvent.Key(TestEventInt)", TestEventIntKey.toString())
24+
assertEquals("ChannelEvent.Key(TestEventString)", TestEventStringKey.toString())
25+
assertEquals("ChannelEvent.Key(TestEventLong)", TestEventLongKey.toString())
26+
}
27+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.hoc081098.channeleventbus
2+
3+
import kotlin.jvm.JvmField
4+
5+
@JvmField
6+
val TestEventIntKey = ChannelEventKey(TestEventInt::class)
7+
8+
@JvmField
9+
val TestEventStringKey = ChannelEventKey(TestEventString::class)
10+
11+
@JvmField
12+
val TestEventLongKey = ChannelEventKey(TestEventLong::class)
13+
14+
data class TestEventInt(val payload: Int) : ChannelEvent<TestEventInt> {
15+
override val key get() = Key
16+
17+
companion object Key : ChannelEventKey<TestEventInt>(TestEventInt::class)
18+
}
19+
20+
data class TestEventString(val payload: String) : ChannelEvent<TestEventString> {
21+
override val key get() = Key
22+
23+
companion object Key : ChannelEventKey<TestEventString>(TestEventString::class)
24+
}
25+
26+
data class TestEventLong(val payload: Long) : ChannelEvent<TestEventLong> {
27+
override val key get() = Key
28+
29+
companion object Key : ChannelEventKey<TestEventLong>(TestEventLong::class)
30+
}

0 commit comments

Comments
 (0)