Add unit test on MatrixTimelineDiffProcessor
This commit is contained in:
parent
98abb7827e
commit
f91d0688d8
2 changed files with 204 additions and 4 deletions
|
|
@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import org.matrix.rustcomponents.sdk.TimelineChange
|
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
import org.matrix.rustcomponents.sdk.TimelineDiffInterface
|
||||||
import org.matrix.rustcomponents.sdk.TimelineItem
|
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ internal class MatrixTimelineDiffProcessor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun postDiffs(diffs: List<TimelineDiff>) {
|
suspend fun postDiffs(diffs: List<TimelineDiffInterface>) {
|
||||||
updateTimelineItems {
|
updateTimelineItems {
|
||||||
Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}")
|
Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}")
|
||||||
diffs.forEach { diff ->
|
diffs.forEach { diff ->
|
||||||
|
|
@ -52,7 +52,7 @@ internal class MatrixTimelineDiffProcessor(
|
||||||
timelineItems.value = mutableTimelineItems
|
timelineItems.value = mutableTimelineItems
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiff) {
|
private fun MutableList<MatrixTimelineItem>.applyDiff(diff: TimelineDiffInterface) {
|
||||||
when (diff.change()) {
|
when (diff.change()) {
|
||||||
TimelineChange.APPEND -> {
|
TimelineChange.APPEND -> {
|
||||||
val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return
|
val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return
|
||||||
|
|
@ -100,7 +100,8 @@ internal class MatrixTimelineDiffProcessor(
|
||||||
clear()
|
clear()
|
||||||
}
|
}
|
||||||
TimelineChange.TRUNCATE -> {
|
TimelineChange.TRUNCATE -> {
|
||||||
// Not supported
|
val index = diff.truncate() ?: return
|
||||||
|
subList(index.toInt(), size).clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.matrix.impl.timeline
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
||||||
|
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
|
||||||
|
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
|
||||||
|
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||||
|
import org.matrix.rustcomponents.sdk.InsertData
|
||||||
|
import org.matrix.rustcomponents.sdk.NoPointer
|
||||||
|
import org.matrix.rustcomponents.sdk.SetData
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineChange
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineDiffInterface
|
||||||
|
import org.matrix.rustcomponents.sdk.TimelineItem
|
||||||
|
import org.matrix.rustcomponents.sdk.VirtualTimelineItem
|
||||||
|
|
||||||
|
open class FakeTimelineDiff(
|
||||||
|
private val change: TimelineChange,
|
||||||
|
private val item: TimelineItem? = FakeTimelineItem()
|
||||||
|
) : TimelineDiffInterface {
|
||||||
|
override fun change() = change
|
||||||
|
override fun append(): List<TimelineItem>? = item?.let { listOf(it) }
|
||||||
|
override fun insert(): InsertData? = item?.let { InsertData(1u, it) }
|
||||||
|
override fun pushBack(): TimelineItem? = item
|
||||||
|
override fun pushFront(): TimelineItem? = item
|
||||||
|
override fun remove(): UInt? = 1u
|
||||||
|
override fun reset(): List<TimelineItem>? = item?.let { listOf(it) }
|
||||||
|
override fun set(): SetData? = item?.let { SetData(1u, it) }
|
||||||
|
override fun truncate(): UInt? = 1u
|
||||||
|
}
|
||||||
|
|
||||||
|
class MatrixTimelineDiffProcessorTest {
|
||||||
|
private val timelineItems = MutableStateFlow<List<MatrixTimelineItem>>(emptyList())
|
||||||
|
|
||||||
|
private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())
|
||||||
|
private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem())
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Append adds new entries at the end of the list`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.APPEND)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(2)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
MatrixTimelineItem.Other,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `PushBack adds a new entry at the end of the list`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_BACK)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(2)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
MatrixTimelineItem.Other,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `PushFront inserts a new entry at the start of the list`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_FRONT)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(2)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
MatrixTimelineItem.Other,
|
||||||
|
anEvent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Set replaces an entry at some index`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.SET)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(2)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
MatrixTimelineItem.Other
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Insert inserts a new entry at the provided index`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.INSERT)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(3)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
MatrixTimelineItem.Other,
|
||||||
|
anEvent2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Remove removes an entry at some index`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.REMOVE)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(2)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
anEvent2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `PopBack removes an entry at the end of the list`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_BACK)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(1)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `PopFront removes an entry at the start of the list`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_FRONT)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(1)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent2,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Clear removes all the entries`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.CLEAR)))
|
||||||
|
assertThat(timelineItems.value).isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Truncate removes all entries after the provided length`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.TRUNCATE)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(1)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
anEvent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Reset removes all entries and add the provided ones`() = runTest {
|
||||||
|
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||||
|
val processor = createProcessor()
|
||||||
|
processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.RESET)))
|
||||||
|
assertThat(timelineItems.value.count()).isEqualTo(1)
|
||||||
|
assertThat(timelineItems.value).containsExactly(
|
||||||
|
MatrixTimelineItem.Other,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestScope.createProcessor(): MatrixTimelineDiffProcessor {
|
||||||
|
val timelineEventContentMapper = TimelineEventContentMapper()
|
||||||
|
val timelineItemMapper = MatrixTimelineItemMapper(
|
||||||
|
fetchDetailsForEvent = { _ -> Result.success(Unit) },
|
||||||
|
coroutineScope = this,
|
||||||
|
virtualTimelineItemMapper = VirtualTimelineItemMapper(),
|
||||||
|
eventTimelineItemMapper = EventTimelineItemMapper(
|
||||||
|
contentMapper = timelineEventContentMapper
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return MatrixTimelineDiffProcessor(
|
||||||
|
timelineItems,
|
||||||
|
timelineItemFactory = timelineItemMapper,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeTimelineItem : TimelineItem(NoPointer) {
|
||||||
|
override fun asEvent(): EventTimelineItem? = null
|
||||||
|
override fun asVirtual(): VirtualTimelineItem? = null
|
||||||
|
override fun fmtDebug(): String = "fmtDebug"
|
||||||
|
override fun uniqueId(): String = "uniqueId"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue