diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/ChunkEntityTest.kt similarity index 93% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/ChunkEntityTest.kt index 7b0d57abbc..baa1b17bf6 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/ChunkEntityTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/ChunkEntityTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.session.room.timeline +package org.matrix.android.sdk.internal.session.room.timeline import androidx.test.ext.junit.runners.AndroidJUnit4 import com.zhuinden.monarchy.Monarchy @@ -32,9 +32,8 @@ import org.matrix.android.sdk.internal.database.helper.addTimelineEvent import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.ChunkEntity import org.matrix.android.sdk.internal.database.model.SessionRealmModule -import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection import org.matrix.android.sdk.internal.util.time.DefaultClock -import org.matrix.android.sdk.session.room.timeline.RoomDataHelper.createFakeMessageEvent +import org.matrix.android.sdk.internal.session.room.timeline.RoomDataHelper.createFakeMessageEvent @RunWith(AndroidJUnit4::class) internal class ChunkEntityTest : InstrumentedTest { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/RoomDataHelper.kt similarity index 96% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/RoomDataHelper.kt index 53585ae82a..204442c2a9 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/RoomDataHelper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.session.room.timeline +package org.matrix.android.sdk.internal.session.room.timeline import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistorTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistorTest.kt new file mode 100644 index 0000000000..e83915c3f4 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistorTest.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.timeline + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.zhuinden.monarchy.Monarchy +import io.realm.Realm +import io.realm.RealmConfiguration +import io.realm.kotlin.executeTransactionAwait +import kotlinx.coroutines.runBlocking +import org.amshove.kluent.shouldBe +import org.amshove.kluent.shouldBeEqualTo +import org.amshove.kluent.shouldNotBe +import org.junit.After +import org.junit.Before +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.internal.database.model.ChunkEntity +import org.matrix.android.sdk.internal.database.model.ChunkEntityFields +import org.matrix.android.sdk.internal.database.model.SessionRealmModule +import org.matrix.android.sdk.internal.session.room.timeline.fakes.FakeLightweightSettingsStorage +import org.matrix.android.sdk.internal.session.room.timeline.fakes.FakeStreamEventsManager +import org.matrix.android.sdk.internal.session.room.timeline.fakes.FakeTokenChunkEvent +import org.matrix.android.sdk.internal.session.room.timeline.fixtures.aListOfTextMessageEvents +import org.matrix.android.sdk.internal.util.time.DefaultClock + +@RunWith(AndroidJUnit4::class) +@FixMethodOrder(MethodSorters.JVM) +class TokenChunkEventPersistorTest : InstrumentedTest { + + private lateinit var monarchy: Monarchy + private lateinit var realm: Realm + private val clock = DefaultClock() + private val userId = "@userId:server.com" + private val lightweightSettingsStorage = FakeLightweightSettingsStorage() + private val streamEventsManager = FakeStreamEventsManager().apply { + givenDispatchPaginatedEventReceived() + } + + @Before + fun setup() { + Realm.init(context()) + val testConfig = RealmConfiguration.Builder() + .inMemory() + .name("TokenChunkEventPersistorTest") + .modules(SessionRealmModule()) + .build() + monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build() + realm = Realm.getInstance(monarchy.realmConfiguration) + } + + @After + fun tearDown() { + realm.close() + } + + @Test + fun given_new_chunk_events_should_all_be_added_and_unique() = runBlocking { + val roomId = "room-id" + val tokenChunkEventPersistor = + TokenChunkEventPersistor(monarchy, userId, lightweightSettingsStorage, liveEventManager = { streamEventsManager.instance }, clock) + val fakeTokenChunkEvent = FakeTokenChunkEvent( + start = "start", + end = "end", + events = aListOfTextMessageEvents(10, roomId = roomId) + ) + val result = tokenChunkEventPersistor.insertInDb(fakeTokenChunkEvent, roomId, direction = PaginationDirection.BACKWARDS) + result shouldBeEqualTo TokenChunkEventPersistor.Result.SUCCESS + realm.refresh() + val chunkEntity = realm.where(ChunkEntity::class.java) + .equalTo(ChunkEntityFields.NEXT_TOKEN, "start") + .equalTo(ChunkEntityFields.PREV_TOKEN, "end") + .findFirst()!! + chunkEntity.nextChunk shouldBe null + chunkEntity.prevChunk shouldBe null + chunkEntity.timelineEvents.size shouldBeEqualTo 10 + Unit + } + +} diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeGetContextOfEventTask.kt similarity index 77% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeGetContextOfEventTask.kt index ccf1c7c2c9..3ccc986ace 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeGetContextOfEventTask.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeGetContextOfEventTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.session.room.timeline +package org.matrix.android.sdk.internal.session.room.timeline.fakes import org.matrix.android.sdk.internal.session.room.timeline.GetContextOfEventTask import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection +import org.matrix.android.sdk.internal.session.room.timeline.RoomDataHelper import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEventPersistor import kotlin.random.Random @@ -30,6 +31,10 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent Random.nextLong().toString(), fakeEvents ) - return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS) + return tokenChunkEventPersistor.insertInDb( + receivedChunk = tokenChunkEvent, + roomId = params.roomId, + direction = PaginationDirection.BACKWARDS + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeLightweightSettingsStorage.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeLightweightSettingsStorage.kt new file mode 100644 index 0000000000..86f8887d96 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeLightweightSettingsStorage.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.timeline.fakes + +import org.matrix.android.sdk.api.settings.LightweightSettingsStorage + +internal class FakeLightweightSettingsStorage : LightweightSettingsStorage { + + private var threadMessageEnabled = false + + override fun setThreadMessagesEnabled(enabled: Boolean) { + threadMessageEnabled = enabled + } + + override fun areThreadMessagesEnabled(): Boolean { + return threadMessageEnabled + } +} diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakePaginationTask.kt similarity index 76% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakePaginationTask.kt index f241be0c5c..e2efdac7bd 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakePaginationTask.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakePaginationTask.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,10 @@ * limitations under the License. */ -package org.matrix.android.sdk.session.room.timeline +package org.matrix.android.sdk.internal.session.room.timeline.fakes import org.matrix.android.sdk.internal.session.room.timeline.PaginationTask +import org.matrix.android.sdk.internal.session.room.timeline.RoomDataHelper import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEventPersistor import javax.inject.Inject import kotlin.random.Random @@ -26,6 +27,10 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven override suspend fun execute(params: PaginationTask.Params): TokenChunkEventPersistor.Result { val fakeEvents = RoomDataHelper.createFakeListOfEvents(30) val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong().toString(), fakeEvents) - return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction) + return tokenChunkEventPersistor.insertInDb( + receivedChunk = tokenChunkEvent, + roomId = params.roomId, + direction = params.direction + ) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeStreamEventsManager.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeStreamEventsManager.kt new file mode 100644 index 0000000000..13dbe690b4 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeStreamEventsManager.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.timeline.fakes + +import io.mockk.every +import io.mockk.just +import io.mockk.mockk +import io.mockk.runs +import org.matrix.android.sdk.internal.session.StreamEventsManager + +internal class FakeStreamEventsManager { + + val instance = mockk() + + fun givenDispatchPaginatedEventReceived() { + every { instance.dispatchPaginatedEventReceived(any(), any()) } just runs + } +} diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeTokenChunkEvent.kt similarity index 85% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeTokenChunkEvent.kt index 2e9478ba7e..e01cfbc1fa 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/FakeTokenChunkEvent.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fakes/FakeTokenChunkEvent.kt @@ -1,11 +1,11 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.session.room.timeline +package org.matrix.android.sdk.internal.session.room.timeline.fakes import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.internal.session.room.timeline.TokenChunkEvent diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fixtures/EventFixture.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fixtures/EventFixture.kt new file mode 100644 index 0000000000..15c54bc663 --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/timeline/fixtures/EventFixture.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.internal.session.room.timeline.fixtures + +import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.toContent +import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.model.RoomMemberContent +import org.matrix.android.sdk.api.session.room.model.RoomNameContent +import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent +import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent +import org.matrix.android.sdk.api.session.room.model.message.MessageType + +internal fun aTextMessageEvent( + roomId: String = "room-id", + eventId: String = "event-id", + senderId: String = "sender-id", + body: String = "body" +): Event = Event( + type = EventType.MESSAGE, + eventId = eventId, + content = MessageTextContent( + msgType = MessageType.MSGTYPE_TEXT, + body = body + ).toContent(), + prevContent = null, + originServerTs = 0, + senderId = senderId, + stateKey = null, + roomId = roomId, + unsignedData = null, + redacts = null +) + +internal fun aRoomCreateEvent( + roomId: String = "room-id", + eventId: String = "event-id", + senderId: String = "sender-id", +): Event = Event( + type = EventType.STATE_ROOM_CREATE, + eventId = eventId, + content = RoomCreateContent( + creator = senderId + ).toContent(), + prevContent = null, + originServerTs = 0, + senderId = senderId, + stateKey = "", + roomId = roomId, + unsignedData = null, + redacts = null +) + +internal fun aRoomMemberEvent( + roomId: String = "room-id", + eventId: String = "event-id", + senderId: String = "sender-id", + membership: Membership = Membership.JOIN, + displayName: String = "Alice", + + ): Event = Event( + type = EventType.STATE_ROOM_MEMBER, + eventId = eventId, + content = RoomMemberContent( + membership = membership, + displayName = displayName + ).toContent(), + prevContent = null, + originServerTs = 0, + senderId = senderId, + stateKey = senderId, + roomId = roomId, + unsignedData = null, + redacts = null +) + +internal fun aRoomNameEvent( + roomId: String = "room-id", + eventId: String = "event-id", + senderId: String = "sender-id", + roomName: String = "Alice and Bob Room" +): Event = Event( + type = EventType.STATE_ROOM_NAME, + eventId = eventId, + content = RoomNameContent( + name = roomName + ).toContent(), + prevContent = null, + originServerTs = 0, + senderId = senderId, + stateKey = "", + roomId = roomId, + unsignedData = null, + redacts = null +) + +internal fun aListOfTextMessageEvents( + size: Int = 10, + roomId: String = "room-id", + eventIdPrefix: String = "event-id", + senderId: String = "sender-id", + bodyPrefix: String = "body" +) = (0 until size).map { + aTextMessageEvent( + roomId = roomId, + eventId = "{$eventIdPrefix}_{$it}", + senderId = senderId, + body = "{$bodyPrefix}_{$it}", + ) +}