Browse Source

Use backgroundScope for TimelineItemsSubscriberTest

pull/3554/head
Benoit Marty 3 weeks ago
parent
commit
b9c9706c48
  1. 182
      libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt

182
libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/TimelineItemsSubscriberTest.kt

@ -16,7 +16,6 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineD
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineItem import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineItem
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.runCancellableScopeTestWithTestScope
import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -25,6 +24,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test
import org.matrix.rustcomponents.sdk.Timeline import org.matrix.rustcomponents.sdk.Timeline
import org.matrix.rustcomponents.sdk.TimelineChange import org.matrix.rustcomponents.sdk.TimelineChange
@ -33,115 +33,107 @@ import uniffi.matrix_sdk_ui.EventItemOrigin
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class TimelineItemsSubscriberTest { class TimelineItemsSubscriberTest {
@Test @Test
fun `when timeline emits an empty list of items, the flow must emits an empty list`() { fun `when timeline emits an empty list of items, the flow must emits an empty list`() = runTest {
runCancellableScopeTestWithTestScope { testScope, cancellableScope -> val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) val timeline = FakeRustTimeline()
val timeline = FakeRustTimeline() val timelineItemsSubscriber = createTimelineItemsSubscriber(
val timelineItemsSubscriber = testScope.createTimelineItemsSubscriber( coroutineScope = backgroundScope,
coroutineScope = cancellableScope, timeline = timeline,
timeline = timeline, timelineItems = timelineItems,
timelineItems = timelineItems, )
) timelineItems.test {
timelineItems.test { timelineItemsSubscriber.subscribeIfNeeded()
timelineItemsSubscriber.subscribeIfNeeded() // Wait for the listener to be set.
// Wait for the listener to be set. runCurrent()
testScope.runCurrent() timeline.emitDiff(listOf(FakeRustTimelineDiff(item = null, change = TimelineChange.RESET)))
timeline.emitDiff(listOf(FakeRustTimelineDiff(item = null, change = TimelineChange.RESET))) val final = awaitItem()
val final = awaitItem() assertThat(final).isEmpty()
assertThat(final).isEmpty() timelineItemsSubscriber.unsubscribeIfNeeded()
timelineItemsSubscriber.unsubscribeIfNeeded()
}
} }
} }
@Test @Test
fun `when timeline emits a non empty list of items, the flow must emits a non empty list`() { fun `when timeline emits a non empty list of items, the flow must emits a non empty list`() = runTest {
runCancellableScopeTestWithTestScope { testScope, cancellableScope -> val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) val timeline = FakeRustTimeline()
val timeline = FakeRustTimeline() val timelineItemsSubscriber = createTimelineItemsSubscriber(
val timelineItemsSubscriber = testScope.createTimelineItemsSubscriber( coroutineScope = backgroundScope,
coroutineScope = cancellableScope, timeline = timeline,
timeline = timeline, timelineItems = timelineItems,
timelineItems = timelineItems, )
) timelineItems.test {
timelineItems.test { timelineItemsSubscriber.subscribeIfNeeded()
timelineItemsSubscriber.subscribeIfNeeded() // Wait for the listener to be set.
// Wait for the listener to be set. runCurrent()
testScope.runCurrent() timeline.emitDiff(listOf(FakeRustTimelineDiff(item = FakeRustTimelineItem(), change = TimelineChange.RESET)))
timeline.emitDiff(listOf(FakeRustTimelineDiff(item = FakeRustTimelineItem(), change = TimelineChange.RESET))) val final = awaitItem()
val final = awaitItem() assertThat(final).isNotEmpty()
assertThat(final).isNotEmpty() timelineItemsSubscriber.unsubscribeIfNeeded()
timelineItemsSubscriber.unsubscribeIfNeeded()
}
} }
} }
@Test @Test
fun `when timeline emits an item with SYNC origin, the callback onNewSyncedEvent is invoked`() { fun `when timeline emits an item with SYNC origin, the callback onNewSyncedEvent is invoked`() = runTest {
runCancellableScopeTestWithTestScope { testScope, cancellableScope -> val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE) val timeline = FakeRustTimeline()
val timeline = FakeRustTimeline() val onNewSyncedEventRecorder = lambdaRecorder<Unit> { }
val onNewSyncedEventRecorder = lambdaRecorder<Unit> { } val timelineItemsSubscriber = createTimelineItemsSubscriber(
val timelineItemsSubscriber = testScope.createTimelineItemsSubscriber( coroutineScope = backgroundScope,
coroutineScope = cancellableScope, timeline = timeline,
timeline = timeline, timelineItems = timelineItems,
timelineItems = timelineItems, onNewSyncedEvent = onNewSyncedEventRecorder,
onNewSyncedEvent = onNewSyncedEventRecorder, )
) timelineItems.test {
timelineItems.test { timelineItemsSubscriber.subscribeIfNeeded()
timelineItemsSubscriber.subscribeIfNeeded() // Wait for the listener to be set.
// Wait for the listener to be set. runCurrent()
testScope.runCurrent() timeline.emitDiff(
timeline.emitDiff( listOf(
listOf( FakeRustTimelineDiff(
FakeRustTimelineDiff( item = FakeRustTimelineItem(
item = FakeRustTimelineItem( asEventResult = FakeRustEventTimelineItem(origin = EventItemOrigin.SYNC)
asEventResult = FakeRustEventTimelineItem(origin = EventItemOrigin.SYNC) ),
), change = TimelineChange.RESET,
change = TimelineChange.RESET,
)
) )
) )
val final = awaitItem()
assertThat(final).isNotEmpty()
timelineItemsSubscriber.unsubscribeIfNeeded()
}
onNewSyncedEventRecorder.assertions().isCalledOnce()
}
}
@Test
fun `multiple subscriptions does not have side effect`() {
runCancellableScopeTestWithTestScope { testScope, cancellableScope ->
val timelineItemsSubscriber = testScope.createTimelineItemsSubscriber(
coroutineScope = cancellableScope,
) )
timelineItemsSubscriber.subscribeIfNeeded() val final = awaitItem()
timelineItemsSubscriber.subscribeIfNeeded() assertThat(final).isNotEmpty()
timelineItemsSubscriber.unsubscribeIfNeeded()
timelineItemsSubscriber.unsubscribeIfNeeded() timelineItemsSubscriber.unsubscribeIfNeeded()
} }
onNewSyncedEventRecorder.assertions().isCalledOnce()
} }
private fun TestScope.createTimelineItemsSubscriber( @Test
coroutineScope: CoroutineScope, fun `multiple subscriptions does not have side effect`() = runTest {
timeline: Timeline = FakeRustTimeline(), val timelineItemsSubscriber = createTimelineItemsSubscriber(
timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE), coroutineScope = backgroundScope,
initLatch: CompletableDeferred<Unit> = CompletableDeferred(),
isTimelineInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false),
onNewSyncedEvent: () -> Unit = { lambdaError() },
): TimelineItemsSubscriber {
return TimelineItemsSubscriber(
timelineCoroutineScope = coroutineScope,
dispatcher = StandardTestDispatcher(testScheduler),
timeline = timeline,
timelineDiffProcessor = createMatrixTimelineDiffProcessor(timelineItems),
initLatch = initLatch,
isTimelineInitialized = isTimelineInitialized,
onNewSyncedEvent = onNewSyncedEvent,
) )
timelineItemsSubscriber.subscribeIfNeeded()
timelineItemsSubscriber.subscribeIfNeeded()
timelineItemsSubscriber.unsubscribeIfNeeded()
timelineItemsSubscriber.unsubscribeIfNeeded()
} }
} }
private fun TestScope.createTimelineItemsSubscriber(
coroutineScope: CoroutineScope,
timeline: Timeline = FakeRustTimeline(),
timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> = MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE),
initLatch: CompletableDeferred<Unit> = CompletableDeferred(),
isTimelineInitialized: MutableStateFlow<Boolean> = MutableStateFlow(false),
onNewSyncedEvent: () -> Unit = { lambdaError() },
): TimelineItemsSubscriber {
return TimelineItemsSubscriber(
timelineCoroutineScope = coroutineScope,
dispatcher = StandardTestDispatcher(testScheduler),
timeline = timeline,
timelineDiffProcessor = createMatrixTimelineDiffProcessor(timelineItems),
initLatch = initLatch,
isTimelineInitialized = isTimelineInitialized,
onNewSyncedEvent = onNewSyncedEvent,
)
}

Loading…
Cancel
Save