From c8c79319eb06f30313067676feedb8407744f0d6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 09:50:29 +0200 Subject: [PATCH 01/25] Add first test on RustMatrixClient --- .../libraries/matrix/impl/RustMatrixClient.kt | 3 ++ .../matrix/impl/RustMatrixClientFactory.kt | 3 ++ .../matrix/impl/room/RustRoomFactory.kt | 9 +--- .../room/TimelineEventTypeFilterFactory.kt | 30 ++++++++++++ .../matrix/impl/RustMatrixClientTest.kt | 47 +++++++++++++++++++ .../impl/fixtures/fakes/FakeRustClient.kt | 39 +++++++++++++++ .../impl/fixtures/fakes/FakeRustEncryption.kt | 24 ++++++++++ .../fakes/FakeRustNotificationClient.kt | 13 +++++ .../fakes/FakeRustNotificationSettings.kt | 20 ++++++++ .../impl/fixtures/fakes/FakeRustRoomList.kt | 13 +++++ .../fixtures/fakes/FakeRustRoomListService.kt | 18 +++++++ .../fixtures/fakes/FakeRustSyncService.kt | 18 +++++++ .../impl/fixtures/fakes/FakeRustTaskHandle.kt | 16 +++++++ .../fakes/FakeRustTimelineEventTypeFilter.kt | 13 +++++ .../FakeTimelineEventTypeFilterFactory.kt | 18 +++++++ .../roomlist/RoomSummaryListProcessorTest.kt | 36 ++------------ 16 files changed, 280 insertions(+), 40 deletions(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/TimelineEventTypeFilterFactory.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustEncryption.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomList.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncService.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTaskHandle.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEventTypeFilter.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/FakeTimelineEventTypeFilterFactory.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index a49db1ccd2..f32401f0a6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -54,6 +54,7 @@ import io.element.android.libraries.matrix.impl.pushers.RustPushersService import io.element.android.libraries.matrix.impl.room.RoomContentForwarder import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber import io.element.android.libraries.matrix.impl.room.RustRoomFactory +import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewMapper import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory @@ -123,6 +124,7 @@ class RustMatrixClient( baseCacheDirectory: File, private val clock: SystemClock, private val sessionDelegate: RustClientSessionDelegate, + timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) override val deviceId: DeviceId = DeviceId(client.deviceId()) @@ -185,6 +187,7 @@ class RustMatrixClient( systemClock = clock, roomContentForwarder = RoomContentForwarder(innerRoomListService), roomSyncSubscriber = roomSyncSubscriber, + timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, ) override val mediaLoader: MatrixMediaLoader = RustMediaLoader( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 512b6e8ea2..51c502ce6a 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.impl.certificates.UserCertificatesPro import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.impl.paths.getSessionPaths import io.element.android.libraries.matrix.impl.proxy.ProxyProvider +import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory import io.element.android.libraries.matrix.impl.util.anonymizedTokens import io.element.android.libraries.network.useragent.UserAgentProvider import io.element.android.libraries.sessionstorage.api.SessionData @@ -45,6 +46,7 @@ class RustMatrixClientFactory @Inject constructor( private val clock: SystemClock, private val utdTracker: UtdTracker, private val featureFlagService: FeatureFlagService, + private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers) @@ -76,6 +78,7 @@ class RustMatrixClientFactory @Inject constructor( baseCacheDirectory = cacheDirectory, clock = clock, sessionDelegate = sessionDelegate, + timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt index a440578513..2e41e36183 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RustRoomFactory.kt @@ -27,12 +27,10 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext -import org.matrix.rustcomponents.sdk.FilterTimelineEventType import org.matrix.rustcomponents.sdk.Membership import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomListException import org.matrix.rustcomponents.sdk.RoomListItem -import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter import timber.log.Timber import org.matrix.rustcomponents.sdk.RoomListService as InnerRoomListService @@ -49,6 +47,7 @@ class RustRoomFactory( private val roomListService: RoomListService, private val innerRoomListService: InnerRoomListService, private val roomSyncSubscriber: RoomSyncSubscriber, + private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, ) { @OptIn(ExperimentalCoroutinesApi::class) private val dispatcher = dispatchers.io.limitedParallelism(1) @@ -74,11 +73,7 @@ class RustRoomFactory( private val eventFilters = TimelineConfig.excludedEvents .takeIf { it.isNotEmpty() } ?.let { listStateEventType -> - TimelineEventTypeFilter.exclude( - listStateEventType.map { stateEventType -> - FilterTimelineEventType.State(stateEventType.map()) - } - ) + timelineEventTypeFilterFactory.create(listStateEventType) } suspend fun destroy() { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/TimelineEventTypeFilterFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/TimelineEventTypeFilterFactory.kt new file mode 100644 index 0000000000..b3689dc137 --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/TimelineEventTypeFilterFactory.kt @@ -0,0 +1,30 @@ +/* + * 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.room + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.AppScope +import io.element.android.libraries.matrix.api.room.StateEventType +import org.matrix.rustcomponents.sdk.FilterTimelineEventType +import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter +import javax.inject.Inject + +interface TimelineEventTypeFilterFactory { + fun create(listStateEventType: List): TimelineEventTypeFilter +} + +@ContributesBinding(AppScope::class) +class RustTimelineEventTypeFilterFactory @Inject constructor() : TimelineEventTypeFilterFactory { + override fun create(listStateEventType: List): TimelineEventTypeFilter { + return TimelineEventTypeFilter.exclude( + listStateEventType.map { stateEventType -> + FilterTimelineEventType.State(stateEventType.map()) + } + ) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt new file mode 100644 index 0000000000..a7cc5fcb2a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -0,0 +1,47 @@ +/* + * 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 + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClient +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustSyncService +import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory +import io.element.android.libraries.matrix.test.A_DEVICE_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test +import java.io.File + +class RustMatrixClientTest { + @Test + fun `ensure that sessionId and deviceId can be retrieved from the client`() = runTest { + val sessionStore = InMemorySessionStore() + val sut = RustMatrixClient( + client = FakeRustClient(), + syncService = FakeRustSyncService(), + sessionStore = InMemorySessionStore(), + appCoroutineScope = this, + dispatchers = testCoroutineDispatchers(), + baseDirectory = File(""), + baseCacheDirectory = File(""), + clock = FakeSystemClock(), + sessionDelegate = RustClientSessionDelegate( + sessionStore = sessionStore, + appCoroutineScope = this, + coroutineDispatchers = testCoroutineDispatchers(), + ), + timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), + ) + assertThat(sut.sessionId).isEqualTo(A_USER_ID) + assertThat(sut.deviceId).isEqualTo(A_DEVICE_ID) + sut.close() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt new file mode 100644 index 0000000000..caa51b3a5c --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt @@ -0,0 +1,39 @@ +/* + * 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.fixtures.fakes + +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession +import io.element.android.libraries.matrix.test.A_DEVICE_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ClientDelegate +import org.matrix.rustcomponents.sdk.Encryption +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.NotificationClient +import org.matrix.rustcomponents.sdk.NotificationProcessSetup +import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.TaskHandle + +class FakeRustClient( + private val userId: String = A_USER_ID.value, + private val deviceId: String = A_DEVICE_ID.value, + private val notificationClient: NotificationClient = FakeRustNotificationClient(), + private val notificationSettings: NotificationSettings = FakeRustNotificationSettings(), + private val encryption: Encryption = FakeRustEncryption(), + private val session: Session = aRustSession(), +) : Client(NoPointer) { + override fun userId(): String = userId + override fun deviceId(): String = deviceId + override suspend fun notificationClient(processSetup: NotificationProcessSetup) = notificationClient + override fun getNotificationSettings(): NotificationSettings = notificationSettings + override fun encryption(): Encryption = encryption + override fun session(): Session = session + override fun setDelegate(delegate: ClientDelegate?): TaskHandle = FakeRustTaskHandle() + override fun cachedAvatarUrl(): String? = null +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustEncryption.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustEncryption.kt new file mode 100644 index 0000000000..4b2f5093b0 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustEncryption.kt @@ -0,0 +1,24 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.Encryption +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RecoveryStateListener +import org.matrix.rustcomponents.sdk.TaskHandle +import org.matrix.rustcomponents.sdk.VerificationStateListener + +class FakeRustEncryption : Encryption(NoPointer) { + override fun verificationStateListener(listener: VerificationStateListener): TaskHandle { + return FakeRustTaskHandle() + } + + override fun recoveryStateListener(listener: RecoveryStateListener): TaskHandle { + return FakeRustTaskHandle() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt new file mode 100644 index 0000000000..477913d127 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt @@ -0,0 +1,13 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.NotificationClient + +class FakeRustNotificationClient : NotificationClient(NoPointer) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt new file mode 100644 index 0000000000..a889530cb2 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt @@ -0,0 +1,20 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate + +class FakeRustNotificationSettings : NotificationSettings(NoPointer) { + private var delegate: NotificationSettingsDelegate? = null + + override fun setDelegate(delegate: NotificationSettingsDelegate?) { + this.delegate = delegate + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomList.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomList.kt new file mode 100644 index 0000000000..3a4417e6df --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomList.kt @@ -0,0 +1,13 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomList + +class FakeRustRoomList : RoomList(NoPointer) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt new file mode 100644 index 0000000000..8d7015f97f --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt @@ -0,0 +1,18 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomList +import org.matrix.rustcomponents.sdk.RoomListService + +class FakeRustRoomListService : RoomListService(NoPointer) { + override suspend fun allRooms(): RoomList { + return FakeRustRoomList() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncService.kt new file mode 100644 index 0000000000..de0a9a4812 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncService.kt @@ -0,0 +1,18 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomListService +import org.matrix.rustcomponents.sdk.SyncService + +class FakeRustSyncService( + private val roomListService: RoomListService = FakeRustRoomListService(), +) : SyncService(NoPointer) { + override fun roomListService(): RoomListService = roomListService +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTaskHandle.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTaskHandle.kt new file mode 100644 index 0000000000..fd287c8acf --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTaskHandle.kt @@ -0,0 +1,16 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.TaskHandle + +class FakeRustTaskHandle : TaskHandle(NoPointer) { + override fun cancel() = Unit + override fun destroy() = Unit +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEventTypeFilter.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEventTypeFilter.kt new file mode 100644 index 0000000000..881cc389b0 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEventTypeFilter.kt @@ -0,0 +1,13 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter + +class FakeRustTimelineEventTypeFilter : TimelineEventTypeFilter(NoPointer) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/FakeTimelineEventTypeFilterFactory.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/FakeTimelineEventTypeFilterFactory.kt new file mode 100644 index 0000000000..cad9e579cd --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/FakeTimelineEventTypeFilterFactory.kt @@ -0,0 +1,18 @@ +/* + * 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.room + +import io.element.android.libraries.matrix.api.room.StateEventType +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineEventTypeFilter +import org.matrix.rustcomponents.sdk.TimelineEventTypeFilter + +class FakeTimelineEventTypeFilterFactory : TimelineEventTypeFilterFactory { + override fun create(listStateEventType: List): TimelineEventTypeFilter { + return FakeRustTimelineEventTypeFilter() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt index d6ed69706c..082ab2523d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt @@ -8,9 +8,9 @@ package io.element.android.libraries.matrix.impl.roomlist import com.google.common.truth.Truth.assertThat -import com.sun.jna.Pointer import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID_2 import io.element.android.libraries.matrix.test.A_ROOM_ID_3 @@ -21,17 +21,8 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomList import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate -import org.matrix.rustcomponents.sdk.RoomListItem -import org.matrix.rustcomponents.sdk.RoomListServiceInterface -import org.matrix.rustcomponents.sdk.RoomListServiceStateListener -import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener -import org.matrix.rustcomponents.sdk.RoomSubscription -import org.matrix.rustcomponents.sdk.TaskHandle - -// NOTE: this class is using a fake implementation of a Rust SDK interface which returns actual Rust objects with pointers. -// Since we don't access the data in those objects, this is fine for our tests, but that's as far as we can test this class. + class RoomSummaryListProcessorTest { private val summaries = MutableStateFlow>(emptyList()) @@ -163,29 +154,8 @@ class RoomSummaryListProcessorTest { private fun TestScope.createProcessor() = RoomSummaryListProcessor( summaries, - fakeRoomListService, + FakeRustRoomListService(), coroutineContext = StandardTestDispatcher(testScheduler), roomSummaryDetailsFactory = RoomSummaryDetailsFactory(), ) - - // Fake room list service that returns Rust objects with null pointers. Luckily for us, they don't crash for our test cases - private val fakeRoomListService = object : RoomListServiceInterface { - override suspend fun allRooms(): RoomList { - return RoomList(Pointer.NULL) - } - - override fun room(roomId: String): RoomListItem { - return RoomListItem(Pointer.NULL) - } - - override fun state(listener: RoomListServiceStateListener): TaskHandle { - return TaskHandle(Pointer.NULL) - } - - override fun syncIndicator(delayBeforeShowingInMs: UInt, delayBeforeHidingInMs: UInt, listener: RoomListServiceSyncIndicatorListener): TaskHandle { - return TaskHandle(Pointer.NULL) - } - - override fun subscribeToRooms(roomIds: List, settings: RoomSubscription?) = Unit - } } From 96a2828de54a9850aeea59d12ca9a54ada2e90f6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 10:22:01 +0200 Subject: [PATCH 02/25] Change signature of RustMatrixClient, val are not always necessary. --- .../android/libraries/matrix/impl/RustMatrixClient.kt | 10 +++++----- .../libraries/matrix/impl/RustMatrixClientFactory.kt | 6 +++--- .../libraries/matrix/impl/RustMatrixClientTest.kt | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index f32401f0a6..c8e1e93eb4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -116,14 +116,14 @@ import org.matrix.rustcomponents.sdk.SyncService as ClientSyncService @OptIn(ExperimentalCoroutinesApi::class) class RustMatrixClient( private val client: Client, - private val syncService: ClientSyncService, + private val baseDirectory: File, private val sessionStore: SessionStore, private val appCoroutineScope: CoroutineScope, - private val dispatchers: CoroutineDispatchers, - private val baseDirectory: File, - baseCacheDirectory: File, - private val clock: SystemClock, private val sessionDelegate: RustClientSessionDelegate, + syncService: ClientSyncService, + dispatchers: CoroutineDispatchers, + baseCacheDirectory: File, + clock: SystemClock, timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 51c502ce6a..507e63b4e7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -70,14 +70,14 @@ class RustMatrixClientFactory @Inject constructor( RustMatrixClient( client = client, - syncService = syncService, + baseDirectory = baseDirectory, sessionStore = sessionStore, appCoroutineScope = appCoroutineScope, + sessionDelegate = sessionDelegate, + syncService = syncService, dispatchers = coroutineDispatchers, - baseDirectory = baseDirectory, baseCacheDirectory = cacheDirectory, clock = clock, - sessionDelegate = sessionDelegate, timelineEventTypeFilterFactory = timelineEventTypeFilterFactory, ).also { Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'") diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index a7cc5fcb2a..22dd53b7f6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -26,18 +26,18 @@ class RustMatrixClientTest { val sessionStore = InMemorySessionStore() val sut = RustMatrixClient( client = FakeRustClient(), - syncService = FakeRustSyncService(), + baseDirectory = File(""), sessionStore = InMemorySessionStore(), appCoroutineScope = this, - dispatchers = testCoroutineDispatchers(), - baseDirectory = File(""), - baseCacheDirectory = File(""), - clock = FakeSystemClock(), sessionDelegate = RustClientSessionDelegate( sessionStore = sessionStore, appCoroutineScope = this, coroutineDispatchers = testCoroutineDispatchers(), ), + syncService = FakeRustSyncService(), + dispatchers = testCoroutineDispatchers(), + baseCacheDirectory = File(""), + clock = FakeSystemClock(), timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), ) assertThat(sut.sessionId).isEqualTo(A_USER_ID) From 40e8b56f796bf55e26a5d20003d2ad1cf4623502 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 11:32:02 +0200 Subject: [PATCH 03/25] Create a factory function for RustMatrixClient --- .../libraries/matrix/impl/RustMatrixClientTest.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 22dd53b7f6..8ba65beaa2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test import java.io.File @@ -23,8 +24,15 @@ import java.io.File class RustMatrixClientTest { @Test fun `ensure that sessionId and deviceId can be retrieved from the client`() = runTest { + createRustMatrixClient().use { sut -> + assertThat(sut.sessionId).isEqualTo(A_USER_ID) + assertThat(sut.deviceId).isEqualTo(A_DEVICE_ID) + } + } + + private fun TestScope.createRustMatrixClient(): RustMatrixClient { val sessionStore = InMemorySessionStore() - val sut = RustMatrixClient( + return RustMatrixClient( client = FakeRustClient(), baseDirectory = File(""), sessionStore = InMemorySessionStore(), @@ -40,8 +48,5 @@ class RustMatrixClientTest { clock = FakeSystemClock(), timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), ) - assertThat(sut.sessionId).isEqualTo(A_USER_ID) - assertThat(sut.deviceId).isEqualTo(A_DEVICE_ID) - sut.close() } } From 3f35bf787594e8a0363ef89d018351b166ca54ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 11:34:59 +0200 Subject: [PATCH 04/25] Fix compilation issue --- .../kotlin/io/element/android/samples/minimal/MainActivity.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 19e1390f47..6e912b513a 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -24,6 +24,7 @@ import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.auth.OidcConfigurationProvider import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory +import io.element.android.libraries.matrix.impl.room.RustTimelineEventTypeFilterFactory import io.element.android.libraries.network.useragent.SimpleUserAgentProvider import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore import io.element.android.libraries.sessionstorage.api.LoggedInState @@ -56,6 +57,7 @@ class MainActivity : ComponentActivity() { clock = DefaultSystemClock(), utdTracker = UtdTracker(NoopAnalyticsService()), featureFlagService = AlwaysEnabledFeatureFlagService(), + timelineEventTypeFilterFactory = RustTimelineEventTypeFilterFactory() ), passphraseGenerator = NullPassphraseGenerator(), oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), From 0e90e57444fcf70dac1860ceab92bfe5110a4933 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 12:16:24 +0200 Subject: [PATCH 05/25] Add test skeleton for RustMatrixClientFactory and RustMatrixAuthenticationService --- libraries/matrix/impl/build.gradle.kts | 2 + .../matrix/impl/ClientBuilderProvider.kt | 23 ++++++++ .../matrix/impl/RustMatrixClientFactory.kt | 3 +- .../matrix/impl/FakeClientBuilderProvider.kt | 17 ++++++ .../impl/RustMatrixClientFactoryTest.kt | 57 +++++++++++++++++++ .../impl/auth/FakePassphraseGenerator.kt | 17 ++++++ .../matrix/impl/auth/FakeProxyProvider.kt | 16 ++++++ .../impl/auth/FakeUserCertificatesProvider.kt | 16 ++++++ .../RustMatrixAuthenticationServiceTest.kt | 57 +++++++++++++++++++ .../impl/fixtures/fakes/FakeRustClient.kt | 3 + .../fixtures/fakes/FakeRustClientBuilder.kt | 51 +++++++++++++++++ .../fakes/FakeRustSyncServiceBuilder.kt | 18 ++++++ .../android/libraries/matrix/test/TestData.kt | 1 + 13 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeProxyProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeUserCertificatesProvider.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClientBuilder.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncServiceBuilder.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index c13189b198..4bd7f995d8 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -46,7 +46,9 @@ dependencies { testImplementation(libs.test.junit) testImplementation(libs.test.truth) testImplementation(libs.test.robolectric) + testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.sessionStorage.implMemory) testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt new file mode 100644 index 0000000000..0bd05b4cdc --- /dev/null +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt @@ -0,0 +1,23 @@ +/* + * 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 + +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.libraries.di.AppScope +import org.matrix.rustcomponents.sdk.ClientBuilder + +interface ClientBuilderProvider { + fun provide(): ClientBuilder +} + +@ContributesBinding(AppScope::class) +class RustClientBuilderProvider : ClientBuilderProvider { + override fun provide(): ClientBuilder { + return ClientBuilder() + } +} diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt index 507e63b4e7..e8c5f3dec3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactory.kt @@ -47,6 +47,7 @@ class RustMatrixClientFactory @Inject constructor( private val utdTracker: UtdTracker, private val featureFlagService: FeatureFlagService, private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory, + private val clientBuilderProvider: ClientBuilderProvider, ) { suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) { val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers) @@ -89,7 +90,7 @@ class RustMatrixClientFactory @Inject constructor( passphrase: String?, slidingSyncType: ClientBuilderSlidingSync, ): ClientBuilder { - return ClientBuilder() + return clientBuilderProvider.provide() .sessionPaths( dataPath = sessionPaths.fileDirectory.absolutePath, cachePath = sessionPaths.cacheDirectory.absolutePath, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt new file mode 100644 index 0000000000..be216b3d73 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/FakeClientBuilderProvider.kt @@ -0,0 +1,17 @@ +/* + * 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 + +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClientBuilder +import org.matrix.rustcomponents.sdk.ClientBuilder + +class FakeClientBuilderProvider : ClientBuilderProvider { + override fun provide(): ClientBuilder { + return FakeRustClientBuilder() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt new file mode 100644 index 0000000000..b408574e92 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientFactoryTest.kt @@ -0,0 +1,57 @@ +/* + * 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 + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.test.FakeFeatureFlagService +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.analytics.UtdTracker +import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider +import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider +import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory +import io.element.android.libraries.network.useragent.SimpleUserAgentProvider +import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import java.io.File + +class RustMatrixClientFactoryTest { + @Test + fun test() = runTest { + val sut = createRustMatrixClientFactory() + val result = sut.create(aSessionData()) + assertThat(result.sessionId).isEqualTo(SessionId("@alice:server.org")) + result.close() + } +} + +fun TestScope.createRustMatrixClientFactory( + baseDirectory: File = File("/base"), + cacheDirectory: File = File("/cache"), + sessionStore: SessionStore = InMemorySessionStore(), +) = RustMatrixClientFactory( + baseDirectory = baseDirectory, + cacheDirectory = cacheDirectory, + appCoroutineScope = this, + coroutineDispatchers = testCoroutineDispatchers(), + sessionStore = sessionStore, + userAgentProvider = SimpleUserAgentProvider(), + userCertificatesProvider = FakeUserCertificatesProvider(), + proxyProvider = FakeProxyProvider(), + clock = FakeSystemClock(), + utdTracker = UtdTracker(FakeAnalyticsService()), + featureFlagService = FakeFeatureFlagService(), + timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), + clientBuilderProvider = FakeClientBuilderProvider(), +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt new file mode 100644 index 0000000000..d882606dc2 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakePassphraseGenerator.kt @@ -0,0 +1,17 @@ +/* + * 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.auth + +import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator +import io.element.android.libraries.matrix.test.A_PASSPHRASE + +class FakePassphraseGenerator( + private val passphrase: () -> String? = { A_PASSPHRASE } +) : PassphraseGenerator { + override fun generatePassphrase(): String? = passphrase() +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeProxyProvider.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeProxyProvider.kt new file mode 100644 index 0000000000..3758be64a0 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeProxyProvider.kt @@ -0,0 +1,16 @@ +/* + * 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.auth + +import io.element.android.libraries.matrix.impl.proxy.ProxyProvider + +class FakeProxyProvider : ProxyProvider { + override fun provides(): String? { + return null + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeUserCertificatesProvider.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeUserCertificatesProvider.kt new file mode 100644 index 0000000000..85dd7f0ecc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/FakeUserCertificatesProvider.kt @@ -0,0 +1,16 @@ +/* + * 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.auth + +import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider + +class FakeUserCertificatesProvider : UserCertificatesProvider { + override fun provides(): List { + return emptyList() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt new file mode 100644 index 0000000000..2a3cadd045 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -0,0 +1,57 @@ +/* + * 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.auth + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.impl.createRustMatrixClientFactory +import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory +import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore +import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import java.io.File + +class RustMatrixAuthenticationServiceTest { + @Test + fun `getLatestSessionId should return the value from the store`() = runTest { + val sessionStore = InMemorySessionStore() + val sut = createRustMatrixAuthenticationService( + sessionStore = sessionStore, + ) + assertThat(sut.getLatestSessionId()).isNull() + sessionStore.storeData(aSessionData(sessionId = "@alice:server.org")) + assertThat(sut.getLatestSessionId()).isEqualTo(SessionId("@alice:server.org")) + } + + private fun TestScope.createRustMatrixAuthenticationService( + sessionStore: SessionStore = InMemorySessionStore(), + ): RustMatrixAuthenticationService { + val baseDirectory = File("/base") + val cacheDirectory = File("/cache") + val rustMatrixClientFactory = createRustMatrixClientFactory( + baseDirectory = baseDirectory, + cacheDirectory = cacheDirectory, + sessionStore = sessionStore, + ) + return RustMatrixAuthenticationService( + sessionPathsFactory = SessionPathsFactory(baseDirectory, cacheDirectory), + coroutineDispatchers = testCoroutineDispatchers(), + sessionStore = sessionStore, + rustMatrixClientFactory = rustMatrixClientFactory, + passphraseGenerator = FakePassphraseGenerator(), + oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), + appPreferencesStore = InMemoryAppPreferencesStore(), + ) + } +} + diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt index caa51b3a5c..fd9b02b417 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt @@ -18,6 +18,7 @@ import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SyncServiceBuilder import org.matrix.rustcomponents.sdk.TaskHandle class FakeRustClient( @@ -36,4 +37,6 @@ class FakeRustClient( override fun session(): Session = session override fun setDelegate(delegate: ClientDelegate?): TaskHandle = FakeRustTaskHandle() override fun cachedAvatarUrl(): String? = null + override suspend fun restoreSession(session: Session) = Unit + override fun syncService(): SyncServiceBuilder = FakeRustSyncServiceBuilder() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClientBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClientBuilder.kt new file mode 100644 index 0000000000..5f073b147c --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClientBuilder.kt @@ -0,0 +1,51 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ClientBuilder +import org.matrix.rustcomponents.sdk.ClientSessionDelegate +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.OidcConfiguration +import org.matrix.rustcomponents.sdk.QrCodeData +import org.matrix.rustcomponents.sdk.QrLoginProgressListener +import org.matrix.rustcomponents.sdk.RequestConfig +import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder +import uniffi.matrix_sdk.BackupDownloadStrategy +import uniffi.matrix_sdk_crypto.CollectStrategy + +class FakeRustClientBuilder : ClientBuilder(NoPointer) { + override fun addRootCertificates(certificates: List) = this + override fun autoEnableBackups(autoEnableBackups: Boolean) = this + override fun autoEnableCrossSigning(autoEnableCrossSigning: Boolean) = this + override fun backupDownloadStrategy(backupDownloadStrategy: BackupDownloadStrategy) = this + override fun disableAutomaticTokenRefresh() = this + override fun disableBuiltInRootCertificates() = this + override fun disableSslVerification() = this + override fun enableCrossProcessRefreshLock(processId: String, sessionDelegate: ClientSessionDelegate) = this + override fun homeserverUrl(url: String) = this + override fun passphrase(passphrase: String?) = this + override fun proxy(url: String) = this + override fun requestConfig(config: RequestConfig) = this + override fun roomKeyRecipientStrategy(strategy: CollectStrategy) = this + override fun serverName(serverName: String) = this + override fun serverNameOrHomeserverUrl(serverNameOrUrl: String) = this + override fun sessionPaths(dataPath: String, cachePath: String) = this + override fun setSessionDelegate(sessionDelegate: ClientSessionDelegate) = this + override fun slidingSyncVersionBuilder(versionBuilder: SlidingSyncVersionBuilder) = this + override fun userAgent(userAgent: String) = this + override fun username(username: String) = this + + override suspend fun buildWithQrCode(qrCodeData: QrCodeData, oidcConfiguration: OidcConfiguration, progressListener: QrLoginProgressListener): Client { + return FakeRustClient() + } + + override suspend fun build(): Client { + return FakeRustClient() + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncServiceBuilder.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncServiceBuilder.kt new file mode 100644 index 0000000000..4cb9c0d314 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustSyncServiceBuilder.kt @@ -0,0 +1,18 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SyncService +import org.matrix.rustcomponents.sdk.SyncServiceBuilder +import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate + +class FakeRustSyncServiceBuilder : SyncServiceBuilder(NoPointer) { + override suspend fun withUtdHook(delegate: UnableToDecryptDelegate): SyncServiceBuilder = this + override suspend fun finish(): SyncService = FakeRustSyncService() +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt index add458ae00..d7dfc2dcb3 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/TestData.kt @@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationSettings const val A_USER_NAME = "alice" const val A_PASSWORD = "password" +const val A_PASSPHRASE = "passphrase" const val A_SECRET = "secret" val A_USER_ID = UserId("@alice:server.org") From 86844e0b27f30b2fdce9b07cb17eb2d7361b824e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 12:28:51 +0200 Subject: [PATCH 06/25] Add test on RustClientSessionDelegate --- .../impl/RustClientSessionDelegateTest.kt | 53 +++++++++++++++++++ .../matrix/impl/RustMatrixClientTest.kt | 4 +- .../matrix/impl/fixtures/factories/Session.kt | 8 +-- .../sessionstorage/test/SessionData.kt | 8 +-- 4 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt new file mode 100644 index 0000000000..c5317bfb48 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegateTest.kt @@ -0,0 +1,53 @@ +/* + * 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 + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession +import io.element.android.libraries.sessionstorage.api.SessionStore +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class RustClientSessionDelegateTest { + @Test + fun `saveSessionInKeychain should update the store`() = runTest { + val sessionStore = InMemorySessionStore() + sessionStore.storeData( + aSessionData( + accessToken = "anAccessToken", + refreshToken = "aRefreshToken", + ) + ) + val sut = aRustClientSessionDelegate(sessionStore) + sut.saveSessionInKeychain( + aRustSession( + accessToken = "at", + refreshToken = "rt", + ) + ) + runCurrent() + val result = sessionStore.getLatestSession() + assertThat(result!!.accessToken).isEqualTo("at") + assertThat(result.refreshToken).isEqualTo("rt") + } +} + +fun TestScope.aRustClientSessionDelegate( + sessionStore: SessionStore = InMemorySessionStore(), +) = RustClientSessionDelegate( + sessionStore = sessionStore, + appCoroutineScope = this, + coroutineDispatchers = testCoroutineDispatchers(), +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index 8ba65beaa2..a3b1cea3e7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -37,10 +37,8 @@ class RustMatrixClientTest { baseDirectory = File(""), sessionStore = InMemorySessionStore(), appCoroutineScope = this, - sessionDelegate = RustClientSessionDelegate( + sessionDelegate = aRustClientSessionDelegate( sessionStore = sessionStore, - appCoroutineScope = this, - coroutineDispatchers = testCoroutineDispatchers(), ), syncService = FakeRustSyncService(), dispatchers = testCoroutineDispatchers(), diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt index 64d1667157..21f0506c0c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt @@ -14,11 +14,13 @@ import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SlidingSyncVersion internal fun aRustSession( - proxy: SlidingSyncVersion = SlidingSyncVersion.None + proxy: SlidingSyncVersion = SlidingSyncVersion.None, + accessToken: String = "accessToken", + refreshToken: String = "refreshToken", ): Session { return Session( - accessToken = "accessToken", - refreshToken = "refreshToken", + accessToken = accessToken, + refreshToken = refreshToken, userId = A_USER_ID.value, deviceId = A_DEVICE_ID.value, homeserverUrl = A_HOMESERVER_URL, diff --git a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt index ad62337ae6..9f37d05fba 100644 --- a/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt +++ b/libraries/session-storage/test/src/main/kotlin/io/element/android/libraries/sessionstorage/test/SessionData.kt @@ -16,12 +16,14 @@ fun aSessionData( isTokenValid: Boolean = false, sessionPath: String = "/a/path/to/a/session", cachePath: String = "/a/path/to/a/cache", -): SessionData { + accessToken: String = "anAccessToken", + refreshToken: String? = "aRefreshToken", + ): SessionData { return SessionData( userId = sessionId, deviceId = deviceId, - accessToken = "anAccessToken", - refreshToken = "aRefreshToken", + accessToken = accessToken, + refreshToken = refreshToken, homeserverUrl = "aHomeserverUrl", oidcData = null, slidingSyncProxy = null, From 77e6a9450aa5820d912b3f21e12a71fc3ca87500 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 12:46:24 +0200 Subject: [PATCH 07/25] Cleanup --- .../matrix/impl/RustMatrixClientTest.kt | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt index a3b1cea3e7..36c96d2dfe 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClientTest.kt @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustSyncServi import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore import io.element.android.services.toolbox.test.systemclock.FakeSystemClock import io.element.android.tests.testutils.testCoroutineDispatchers @@ -30,21 +31,20 @@ class RustMatrixClientTest { } } - private fun TestScope.createRustMatrixClient(): RustMatrixClient { - val sessionStore = InMemorySessionStore() - return RustMatrixClient( - client = FakeRustClient(), - baseDirectory = File(""), - sessionStore = InMemorySessionStore(), - appCoroutineScope = this, - sessionDelegate = aRustClientSessionDelegate( - sessionStore = sessionStore, - ), - syncService = FakeRustSyncService(), - dispatchers = testCoroutineDispatchers(), - baseCacheDirectory = File(""), - clock = FakeSystemClock(), - timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), - ) - } + private fun TestScope.createRustMatrixClient( + sessionStore: SessionStore = InMemorySessionStore(), + ) = RustMatrixClient( + client = FakeRustClient(), + baseDirectory = File(""), + sessionStore = sessionStore, + appCoroutineScope = this, + sessionDelegate = aRustClientSessionDelegate( + sessionStore = sessionStore, + ), + syncService = FakeRustSyncService(), + dispatchers = testCoroutineDispatchers(), + baseCacheDirectory = File(""), + clock = FakeSystemClock(), + timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(), + ) } From 47df0d1e4026001ec7ef2817dccd2aa8a5e81a54 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 12:47:53 +0200 Subject: [PATCH 08/25] Add test on RustRoomDirectoryService --- .../RoomDirectorySearchProcessor.kt | 2 +- .../roomdirectory/RustRoomDirectoryList.kt | 2 +- .../fixtures/fakes/FakeRoomDirectorySearch.kt | 13 ++++++++++ .../impl/fixtures/fakes/FakeRustClient.kt | 2 ++ .../RustRoomDirectoryServiceTest.kt | 25 +++++++++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt index e9bed50951..6ae3103448 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt @@ -19,8 +19,8 @@ import kotlin.coroutines.CoroutineContext class RoomDirectorySearchProcessor( private val roomDescriptions: MutableSharedFlow>, private val coroutineContext: CoroutineContext, - private val roomDescriptionMapper: RoomDescriptionMapper, ) { + private val roomDescriptionMapper: RoomDescriptionMapper = RoomDescriptionMapper() private val mutex = Mutex() suspend fun postUpdates(updates: List) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt index 33f571855e..2d627c9358 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt @@ -28,7 +28,7 @@ class RustRoomDirectoryList( ) : RoomDirectoryList { private val hasMoreToLoad = MutableStateFlow(true) private val items = MutableSharedFlow>(replay = 1) - private val processor = RoomDirectorySearchProcessor(items, coroutineContext, RoomDescriptionMapper()) + private val processor = RoomDirectorySearchProcessor(items, coroutineContext) init { launchIn(coroutineScope) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt new file mode 100644 index 0000000000..7ff65167ec --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt @@ -0,0 +1,13 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomDirectorySearch + +class FakeRoomDirectorySearch : RoomDirectorySearch(NoPointer) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt index fd9b02b417..935537a27f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt @@ -17,6 +17,7 @@ import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.RoomDirectorySearch import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SyncServiceBuilder import org.matrix.rustcomponents.sdk.TaskHandle @@ -39,4 +40,5 @@ class FakeRustClient( override fun cachedAvatarUrl(): String? = null override suspend fun restoreSession(session: Session) = Unit override fun syncService(): SyncServiceBuilder = FakeRustSyncServiceBuilder() + override fun roomDirectorySearch(): RoomDirectorySearch = FakeRoomDirectorySearch() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt new file mode 100644 index 0000000000..c9c91713b2 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt @@ -0,0 +1,25 @@ +/* + * 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.roomdirectory + +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClient +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class RustRoomDirectoryServiceTest { + @Test + fun test() = runTest { + val client = FakeRustClient() + val sut = RustRoomDirectoryService( + client = client, + sessionDispatcher = testCoroutineDispatchers().io, + ) + sut.createRoomDirectoryList(this) + } +} From a7d4babf483d9f208ab8febbcfb986985866b2f0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 15:16:19 +0200 Subject: [PATCH 09/25] Inject constructor --- .../android/libraries/matrix/impl/ClientBuilderProvider.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt index 0bd05b4cdc..b4b7497d79 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/ClientBuilderProvider.kt @@ -10,13 +10,14 @@ package io.element.android.libraries.matrix.impl import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope import org.matrix.rustcomponents.sdk.ClientBuilder +import javax.inject.Inject interface ClientBuilderProvider { fun provide(): ClientBuilder } @ContributesBinding(AppScope::class) -class RustClientBuilderProvider : ClientBuilderProvider { +class RustClientBuilderProvider @Inject constructor() : ClientBuilderProvider { override fun provide(): ClientBuilder { return ClientBuilder() } From d1be4349f077e73c08277fb248fffa6e7a04dffc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 15:40:25 +0200 Subject: [PATCH 10/25] Add test on RustRoomDirectoryList --- .../fixtures/factories/RoomDescription.kt | 27 ++++-- .../fixtures/fakes/FakeRoomDirectorySearch.kt | 26 +++++- .../RustRoomDirectoryListTest.kt | 90 +++++++++++++++++++ .../tests/testutils/RunCancellableTest.kt | 10 +++ 4 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt index d80b3d3723..8ade9c0ec2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt @@ -12,15 +12,24 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID import org.matrix.rustcomponents.sdk.PublicRoomJoinRule import org.matrix.rustcomponents.sdk.RoomDescription -internal fun aRustRoomDescription(): RoomDescription { +internal fun aRustRoomDescription( + roomId: String = A_ROOM_ID.value, + name: String? = "name", + topic: String? = "topic", + alias: String? = A_ROOM_ALIAS.value, + avatarUrl: String? = "avatarUrl", + joinRule: PublicRoomJoinRule = PublicRoomJoinRule.PUBLIC, + isWorldReadable: Boolean = true, + joinedMembers: ULong = 2u, +): RoomDescription { return RoomDescription( - roomId = A_ROOM_ID.value, - name = "name", - topic = "topic", - alias = A_ROOM_ALIAS.value, - avatarUrl = "avatarUrl", - joinRule = PublicRoomJoinRule.PUBLIC, - isWorldReadable = true, - joinedMembers = 2u + roomId = roomId, + name = name, + topic = topic, + alias = alias, + avatarUrl = avatarUrl, + joinRule = joinRule, + isWorldReadable = isWorldReadable, + joinedMembers = joinedMembers, ) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt index 7ff65167ec..587b1bf5ce 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRoomDirectorySearch.kt @@ -7,7 +7,31 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes +import io.element.android.tests.testutils.simulateLongTask import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomDirectorySearch +import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntriesListener +import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate +import org.matrix.rustcomponents.sdk.TaskHandle -class FakeRoomDirectorySearch : RoomDirectorySearch(NoPointer) +class FakeRoomDirectorySearch( + var isAtLastPage: Boolean = false, +) : RoomDirectorySearch(NoPointer) { + override suspend fun isAtLastPage(): Boolean { + return isAtLastPage + } + + override suspend fun search(filter: String?, batchSize: UInt) = simulateLongTask { } + override suspend fun nextPage() = simulateLongTask { } + + private var listener: RoomDirectorySearchEntriesListener? = null + + override suspend fun results(listener: RoomDirectorySearchEntriesListener): TaskHandle { + this.listener = listener + return FakeRustTaskHandle() + } + + fun emitResult(roomEntriesUpdate: List) { + listener?.onUpdate(roomEntriesUpdate) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt new file mode 100644 index 0000000000..71003b5b9a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryListTest.kt @@ -0,0 +1,90 @@ +/* + * 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.roomdirectory + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryList +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRoomDirectorySearch +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.tests.testutils.runCancellableScopeTestWithTestScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomDirectorySearch +import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate + +@OptIn(ExperimentalCoroutinesApi::class) +class RustRoomDirectoryListTest { + @Test + fun `check that the state emits the expected values`() = runCancellableScopeTestWithTestScope { testScope, cancellableScope -> + val fakeRoomDirectorySearch = FakeRoomDirectorySearch() + val mapper = RoomDescriptionMapper() + val sut = testScope.createRustRoomDirectoryList( + roomDirectorySearch = fakeRoomDirectorySearch, + scope = cancellableScope, + ) + // Let the mxCallback be ready + testScope.runCurrent() + sut.state.test { + sut.filter("", 20) + fakeRoomDirectorySearch.emitResult( + listOf( + RoomDirectorySearchEntryUpdate.Append(listOf(aRustRoomDescription())) + ) + ) + val initialItem = awaitItem() + assertThat(initialItem).isEqualTo( + RoomDirectoryList.State( + hasMoreToLoad = true, + items = listOf(mapper.map(aRustRoomDescription())) + ) + ) + assertThat(initialItem.hasMoreToLoad).isTrue() + fakeRoomDirectorySearch.isAtLastPage = true + sut.loadMore() + fakeRoomDirectorySearch.emitResult( + listOf( + RoomDirectorySearchEntryUpdate.Append(listOf(aRustRoomDescription(A_ROOM_ID_2.value))) + ) + ) + val nextItem = awaitItem() + assertThat(nextItem).isEqualTo( + RoomDirectoryList.State( + hasMoreToLoad = false, + items = listOf( + mapper.map(aRustRoomDescription()), + ) + ) + ) + val finalItem = awaitItem() + assertThat(finalItem).isEqualTo( + RoomDirectoryList.State( + hasMoreToLoad = false, + items = listOf( + mapper.map(aRustRoomDescription()), + mapper.map(aRustRoomDescription(A_ROOM_ID_2.value)), + ) + ) + ) + } + } + + private fun TestScope.createRustRoomDirectoryList( + roomDirectorySearch: RoomDirectorySearch = FakeRoomDirectorySearch(), + scope: CoroutineScope, + ) = RustRoomDirectoryList( + inner = roomDirectorySearch, + coroutineScope = scope, + coroutineContext = StandardTestDispatcher(testScheduler), + ) +} diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RunCancellableTest.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RunCancellableTest.kt index 64c36f0a8d..c3074aaf35 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RunCancellableTest.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/RunCancellableTest.kt @@ -10,6 +10,7 @@ package io.element.android.tests.testutils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest /** @@ -20,3 +21,12 @@ fun runCancellableScopeTest(block: suspend (CoroutineScope) -> Unit) = runTest { block(scope) scope.cancel() } + +/** + * Run a test with a [CoroutineScope] that will be cancelled automatically and avoiding failing the test. + */ +fun runCancellableScopeTestWithTestScope(block: suspend (testScope: TestScope, cancellableScope: CoroutineScope) -> Unit) = runTest { + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + block(this, scope) + scope.cancel() +} From b67c4287935c1d78f58a5f941e5693bf80a817d0 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 16:00:57 +0200 Subject: [PATCH 11/25] Add test on RoomDirectorySearchProcessor Give the responsibility to the RoomDirectorySearchProcessor to create the `MutableSharedFlow` since it requires a replayCache to work properly. --- .../RoomDirectorySearchProcessor.kt | 5 +- .../roomdirectory/RustRoomDirectoryList.kt | 7 +- .../RoomDirectorySearchProcessorTest.kt | 75 +++++++++++++++++++ 3 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt index 6ae3103448..d3253176a3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessor.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.impl.roomdirectory import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -17,9 +18,11 @@ import timber.log.Timber import kotlin.coroutines.CoroutineContext class RoomDirectorySearchProcessor( - private val roomDescriptions: MutableSharedFlow>, private val coroutineContext: CoroutineContext, ) { + private val roomDescriptions: MutableSharedFlow> = MutableSharedFlow(replay = 1) + val roomDescriptionsFlow: Flow> = roomDescriptions + private val roomDescriptionMapper: RoomDescriptionMapper = RoomDescriptionMapper() private val mutex = Mutex() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt index 2d627c9358..7219e9c3ed 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryList.kt @@ -7,12 +7,10 @@ package io.element.android.libraries.matrix.impl.roomdirectory -import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryList import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOn @@ -27,8 +25,7 @@ class RustRoomDirectoryList( private val coroutineContext: CoroutineContext, ) : RoomDirectoryList { private val hasMoreToLoad = MutableStateFlow(true) - private val items = MutableSharedFlow>(replay = 1) - private val processor = RoomDirectorySearchProcessor(items, coroutineContext) + private val processor = RoomDirectorySearchProcessor(coroutineContext) init { launchIn(coroutineScope) @@ -77,7 +74,7 @@ class RustRoomDirectoryList( } override val state: Flow = - combine(hasMoreToLoad, items) { hasMoreToLoad, items -> + combine(hasMoreToLoad, processor.roomDescriptionsFlow) { hasMoreToLoad, items -> RoomDirectoryList.State( hasMoreToLoad = hasMoreToLoad, items = items diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt new file mode 100644 index 0000000000..be61bd77f2 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt @@ -0,0 +1,75 @@ +/* + * 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.roomdirectory + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_ID_2 +import io.element.android.libraries.matrix.test.A_ROOM_ID_3 +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate + +class RoomDirectorySearchProcessorTest { + private val rustRoom1 = aRustRoomDescription(roomId = A_ROOM_ID.value) + private val rustRoom2 = aRustRoomDescription(roomId = A_ROOM_ID_2.value) + private val rustRoom3 = aRustRoomDescription(roomId = A_ROOM_ID_3.value) + private val mapper = RoomDescriptionMapper() + private val room1 = mapper.map(rustRoom1) + private val room2 = mapper.map(rustRoom2) + private val room3 = mapper.map(rustRoom3) + + @Test + fun test() = runTest { + val sut = RoomDirectorySearchProcessor( + coroutineContext = StandardTestDispatcher(testScheduler), + ) + sut.roomDescriptionsFlow.test { + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Reset(listOf(rustRoom1)))) + assertThat(awaitItem()).isEqualTo(listOf(room1)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Append(listOf(rustRoom2)))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.PushFront(rustRoom3))) + assertThat(awaitItem()).isEqualTo(listOf(room3, room1, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.PopFront)) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.PushBack(rustRoom3))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2, room3)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.PopBack)) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Insert(1u, rustRoom3))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room3, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Remove(1u))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2)) + + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Reset(listOf(rustRoom1, rustRoom2)))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Set(1u, rustRoom3))) + assertThat(awaitItem()).isEqualTo(listOf(room1, room3)) + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Truncate(1u))) + assertThat(awaitItem()).isEqualTo(listOf(room1)) + + sut.postUpdates(listOf(RoomDirectorySearchEntryUpdate.Clear)) + assertThat(awaitItem()).isEmpty() + + // Check that all the actions are performed + sut.postUpdates( + listOf( + RoomDirectorySearchEntryUpdate.PushBack(rustRoom1), + RoomDirectorySearchEntryUpdate.PushBack(rustRoom2), + RoomDirectorySearchEntryUpdate.PushBack(rustRoom3), + ) + ) + assertThat(awaitItem()).isEqualTo(listOf(room1, room2, room3)) + + } + } +} From 1fd1f016be3b542f409aa73141ce2289318c139e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 16:23:39 +0200 Subject: [PATCH 12/25] Add test on RoomListFactory --- .../matrix/impl/roomlist/RoomListFactory.kt | 6 ++-- .../impl/roomlist/RoomListFactoryTest.kt | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt index 66942d0013..77e2de1f94 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt @@ -25,21 +25,21 @@ import org.matrix.rustcomponents.sdk.RoomListEntriesDynamicFilterKind import org.matrix.rustcomponents.sdk.RoomListLoadingState import org.matrix.rustcomponents.sdk.RoomListService import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList internal class RoomListFactory( private val innerRoomListService: RoomListService, private val sessionCoroutineScope: CoroutineScope, - private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory(), ) { + private val roomSummaryDetailsFactory: RoomSummaryDetailsFactory = RoomSummaryDetailsFactory() + /** * Creates a room list that can be used to load more rooms and filter them dynamically. */ fun createRoomList( pageSize: Int, + coroutineContext: CoroutineContext, coroutineScope: CoroutineScope = sessionCoroutineScope, - coroutineContext: CoroutineContext = EmptyCoroutineContext, initialFilter: RoomListFilter = RoomListFilter.all(), innerProvider: suspend () -> InnerRoomList ): DynamicRoomList { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt new file mode 100644 index 0000000000..cd961b54da --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactoryTest.kt @@ -0,0 +1,30 @@ +/* + * 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.roomlist + +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomList +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService +import io.element.android.tests.testutils.runCancellableScopeTest +import org.junit.Test +import kotlin.coroutines.EmptyCoroutineContext + +class RoomListFactoryTest { + @Test + fun `createRoomList should work`() = runCancellableScopeTest { + val sut = RoomListFactory( + innerRoomListService = FakeRustRoomListService(), + sessionCoroutineScope = it, + ) + sut.createRoomList( + pageSize = 10, + coroutineContext = EmptyCoroutineContext, + ) { + FakeRustRoomList() + } + } +} From de7d93e37d3b3fee3bb4519cf3f28ba96f92d76d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 16:41:19 +0200 Subject: [PATCH 13/25] Add test on RustRoomListService --- .../matrix/impl/room/RoomSyncSubscriber.kt | 4 +- .../impl/roomlist/RustRoomListService.kt | 2 +- .../fixtures/fakes/FakeRustRoomListService.kt | 18 ++++++ .../impl/roomlist/RustRoomListServiceTest.kt | 61 +++++++++++++++++++ 4 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListServiceTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt index 792c6cb33d..9ad27a7914 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomSyncSubscriber.kt @@ -15,14 +15,14 @@ import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.RequiredState -import org.matrix.rustcomponents.sdk.RoomListServiceInterface +import org.matrix.rustcomponents.sdk.RoomListService import org.matrix.rustcomponents.sdk.RoomSubscription import timber.log.Timber private const val DEFAULT_TIMELINE_LIMIT = 20u class RoomSyncSubscriber( - private val roomListService: RoomListServiceInterface, + private val roomListService: RoomListService, private val dispatchers: CoroutineDispatchers, ) { private val subscribedRoomIds = mutableSetOf() diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt index ee0be05e4b..f8f2629f36 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListService.kt @@ -31,10 +31,10 @@ private const val DEFAULT_PAGE_SIZE = 20 internal class RustRoomListService( private val innerRoomListService: InnerRustRoomListService, - private val sessionCoroutineScope: CoroutineScope, private val sessionDispatcher: CoroutineDispatcher, private val roomListFactory: RoomListFactory, private val roomSyncSubscriber: RoomSyncSubscriber, + sessionCoroutineScope: CoroutineScope, ) : RoomListService { override fun createRoomList( pageSize: Int, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt index 8d7015f97f..69ef9a4781 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt @@ -10,9 +10,27 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomList import org.matrix.rustcomponents.sdk.RoomListService +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener +import org.matrix.rustcomponents.sdk.TaskHandle class FakeRustRoomListService : RoomListService(NoPointer) { + override suspend fun allRooms(): RoomList { return FakeRustRoomList() } + + private var listener: RoomListServiceSyncIndicatorListener? = null + override fun syncIndicator( + delayBeforeShowingInMs: UInt, + delayBeforeHidingInMs: UInt, + listener: RoomListServiceSyncIndicatorListener, + ): TaskHandle { + this.listener = listener + return FakeRustTaskHandle() + } + + fun emitRoomListServiceSyncIndicator(syncIndicator: RoomListServiceSyncIndicator) { + listener?.onUpdate(syncIndicator) + } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListServiceTest.kt new file mode 100644 index 0000000000..b8af0c2e65 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RustRoomListServiceTest.kt @@ -0,0 +1,61 @@ +/* + * 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.roomlist + +import app.cash.turbine.test +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.roomlist.RoomListService +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListService +import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber +import io.element.android.tests.testutils.runCancellableScopeTestWithTestScope +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator +import org.matrix.rustcomponents.sdk.RoomListService as RustRoomListService + +@OptIn(ExperimentalCoroutinesApi::class) +class RustRoomListServiceTest { + @Test + fun `syncIndicator should emit the expected values`() = runCancellableScopeTestWithTestScope { testScope, cancellableScope -> + val roomListService = FakeRustRoomListService() + val sut = testScope.createRustRoomListService( + sessionCoroutineScope = cancellableScope, + roomListService = roomListService, + ) + // Give time for mxCallback to setup + testScope.runCurrent() + sut.syncIndicator.test { + assertThat(awaitItem()).isEqualTo(RoomListService.SyncIndicator.Hide) + roomListService.emitRoomListServiceSyncIndicator(RoomListServiceSyncIndicator.SHOW) + assertThat(awaitItem()).isEqualTo(RoomListService.SyncIndicator.Show) + roomListService.emitRoomListServiceSyncIndicator(RoomListServiceSyncIndicator.HIDE) + assertThat(awaitItem()).isEqualTo(RoomListService.SyncIndicator.Hide) + } + } +} + +private fun TestScope.createRustRoomListService( + sessionCoroutineScope: CoroutineScope, + roomListService: RustRoomListService = FakeRustRoomListService(), +) = RustRoomListService( + innerRoomListService = roomListService, + sessionDispatcher = StandardTestDispatcher(testScheduler), + roomListFactory = RoomListFactory( + innerRoomListService = roomListService, + sessionCoroutineScope = sessionCoroutineScope, + ), + roomSyncSubscriber = RoomSyncSubscriber( + roomListService = roomListService, + dispatchers = testCoroutineDispatchers(), + ), + sessionCoroutineScope = sessionCoroutineScope, +) From 8127aa6351e1fce7f6e5e7539354d942bd08a262 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 17:06:49 +0200 Subject: [PATCH 14/25] Cleanup constructor and avoid creating many mapper instances --- .../TimelineEventToNotificationContentMapper.kt | 3 +-- .../matrix/impl/room/message/RoomMessageFactory.kt | 6 ++++-- .../matrix/impl/roomlist/RoomSummaryDetailsFactory.kt | 4 +++- .../matrix/impl/timeline/MatrixTimelineItemMapper.kt | 4 ++-- .../impl/timeline/item/event/EventTimelineItemMapper.kt | 4 +++- .../impl/timeline/item/event/TimelineEventContentMapper.kt | 4 +++- 6 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt index bcb694085b..0dccf90fa9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt @@ -19,9 +19,8 @@ import org.matrix.rustcomponents.sdk.StateEventContent import org.matrix.rustcomponents.sdk.TimelineEvent import org.matrix.rustcomponents.sdk.TimelineEventType import org.matrix.rustcomponents.sdk.use -import javax.inject.Inject -class TimelineEventToNotificationContentMapper @Inject constructor() { +class TimelineEventToNotificationContentMapper { fun map(timelineEvent: TimelineEvent): NotificationContent { return timelineEvent.use { timelineEvent.eventType().use { eventType -> diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt index ff1443cf90..920564e74d 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/message/RoomMessageFactory.kt @@ -11,10 +11,12 @@ import io.element.android.libraries.matrix.api.room.message.RoomMessage import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import org.matrix.rustcomponents.sdk.EventTimelineItem as RustEventTimelineItem -class RoomMessageFactory { +class RoomMessageFactory( + private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), +) { fun create(eventTimelineItem: RustEventTimelineItem?): RoomMessage? { eventTimelineItem ?: return null - val mappedTimelineItem = EventTimelineItemMapper().map(eventTimelineItem) + val mappedTimelineItem = eventTimelineItemMapper.map(eventTimelineItem) return RoomMessage( eventId = mappedTimelineItem.eventId ?: return null, event = mappedTimelineItem, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt index a43cd59bdc..92dbed82b6 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryDetailsFactory.kt @@ -19,7 +19,9 @@ import io.element.android.libraries.matrix.impl.room.message.RoomMessageFactory import org.matrix.rustcomponents.sdk.RoomListItem import org.matrix.rustcomponents.sdk.use -class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory()) { +class RoomSummaryDetailsFactory( + private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory(), +) { suspend fun create(roomListItem: RoomListItem): RoomSummary { val roomInfo = roomListItem.roomInfo() val latestRoomMessage = roomListItem.latestEvent().use { event -> diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt index 4ef30e87f9..4096b87ba4 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineItemMapper.kt @@ -19,8 +19,8 @@ import org.matrix.rustcomponents.sdk.TimelineItem class MatrixTimelineItemMapper( private val fetchDetailsForEvent: suspend (EventId) -> Result, private val coroutineScope: CoroutineScope, - private val virtualTimelineItemMapper: VirtualTimelineItemMapper = VirtualTimelineItemMapper(), - private val eventTimelineItemMapper: EventTimelineItemMapper = EventTimelineItemMapper(), + private val virtualTimelineItemMapper: VirtualTimelineItemMapper, + private val eventTimelineItemMapper: EventTimelineItemMapper, ) { fun map(timelineItem: TimelineItem): MatrixTimelineItem = timelineItem.use { val uniqueId = UniqueId(timelineItem.uniqueId()) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt index f83d6d0672..17a33ff93b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/EventTimelineItemMapper.kt @@ -34,7 +34,9 @@ import org.matrix.rustcomponents.sdk.ProfileDetails as RustProfileDetails import org.matrix.rustcomponents.sdk.Receipt as RustReceipt import uniffi.matrix_sdk_ui.EventItemOrigin as RustEventItemOrigin -class EventTimelineItemMapper(private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper()) { +class EventTimelineItemMapper( + private val contentMapper: TimelineEventContentMapper = TimelineEventContentMapper(), +) { fun map(eventTimelineItem: RustEventTimelineItem): EventTimelineItem = eventTimelineItem.use { EventTimelineItem( eventId = it.eventId()?.let(::EventId), diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt index 62a43ce647..474d57a7e1 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/item/event/TimelineEventContentMapper.kt @@ -37,7 +37,9 @@ import org.matrix.rustcomponents.sdk.MembershipChange as RustMembershipChange import org.matrix.rustcomponents.sdk.OtherState as RustOtherState import uniffi.matrix_sdk_crypto.UtdCause as RustUtdCause -class TimelineEventContentMapper(private val eventMessageMapper: EventMessageMapper = EventMessageMapper()) { +class TimelineEventContentMapper( + private val eventMessageMapper: EventMessageMapper = EventMessageMapper(), +) { fun map(content: TimelineItemContent): EventContent { return content.use { content.kind().use { kind -> From e117b74b0b4ff253ebe8305a133a242dfe108a7d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 17:21:26 +0200 Subject: [PATCH 15/25] Fix test --- .../impl/roomdirectory/RustRoomDirectoryServiceTest.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt index c9c91713b2..06b26bcdd4 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RustRoomDirectoryServiceTest.kt @@ -8,18 +8,18 @@ package io.element.android.libraries.matrix.impl.roomdirectory import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClient -import io.element.android.tests.testutils.testCoroutineDispatchers -import kotlinx.coroutines.test.runTest +import io.element.android.tests.testutils.runCancellableScopeTestWithTestScope +import kotlinx.coroutines.test.StandardTestDispatcher import org.junit.Test class RustRoomDirectoryServiceTest { @Test - fun test() = runTest { + fun test() = runCancellableScopeTestWithTestScope { testScope, cancellableScope -> val client = FakeRustClient() val sut = RustRoomDirectoryService( client = client, - sessionDispatcher = testCoroutineDispatchers().io, + sessionDispatcher = StandardTestDispatcher(testScope.testScheduler), ) - sut.createRoomDirectoryList(this) + sut.createRoomDirectoryList(cancellableScope) } } From bfaa9f843c1325a1bdbd7f62793bcd4dbd881a9a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 17:27:55 +0200 Subject: [PATCH 16/25] Add unit test on HomeserverLoginDetails.map() --- .../impl/auth/HomeserverDetailsKtTest.kt | 37 +++++++++++++++++++ .../auth/OidcConfigurationProviderTest.kt | 21 +++++++++++ .../fakes/FakeRustHomeserverLoginDetails.kt | 21 +++++++++++ 3 files changed, 79 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustHomeserverLoginDetails.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt new file mode 100644 index 0000000000..01ca61d433 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/HomeserverDetailsKtTest.kt @@ -0,0 +1,37 @@ +/* + * 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.auth + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustHomeserverLoginDetails +import org.junit.Test + +class HomeserverDetailsKtTest { + @Test + fun `map should be correct`() { + // Given + val homeserverLoginDetails = FakeRustHomeserverLoginDetails( + url = "https://example.org", + supportsPasswordLogin = true, + supportsOidcLogin = false + ) + + // When + val result = homeserverLoginDetails.map() + + // Then + assertThat(result).isEqualTo( + MatrixHomeServerDetails( + url = "https://example.org", + supportsPasswordLogin = true, + supportsOidcLogin = false + ) + ) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt new file mode 100644 index 0000000000..a1348e209e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/OidcConfigurationProviderTest.kt @@ -0,0 +1,21 @@ +/* + * 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.auth + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.OidcConfig +import org.junit.Test +import java.io.File + +class OidcConfigurationProviderTest { + @Test + fun get() { + val result = OidcConfigurationProvider(File("/base")).get() + assertThat(result.redirectUri).isEqualTo(OidcConfig.REDIRECT_URI) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustHomeserverLoginDetails.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustHomeserverLoginDetails.kt new file mode 100644 index 0000000000..52b9cfb2f6 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustHomeserverLoginDetails.kt @@ -0,0 +1,21 @@ +/* + * 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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.HomeserverLoginDetails +import org.matrix.rustcomponents.sdk.NoPointer + +class FakeRustHomeserverLoginDetails( + private val url: String = "https://example.org", + private val supportsPasswordLogin: Boolean = true, + private val supportsOidcLogin: Boolean = false +) : HomeserverLoginDetails(NoPointer) { + override fun url(): String = url + override fun supportsOidcLogin(): Boolean = supportsOidcLogin + override fun supportsPasswordLogin(): Boolean = supportsPasswordLogin +} From 145c40ddfa102f15724ecb24b9a20d5b38fb1190 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 17:35:40 +0200 Subject: [PATCH 17/25] Add unit test on ExternalSession.toSessionData --- .../matrix/impl/mapper/SessionKtTest.kt | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt index 9e6d87957c..b0e1254179 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -8,6 +8,7 @@ package io.element.android.libraries.matrix.impl.mapper import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.external.ExternalSession import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.test.A_DEVICE_ID @@ -81,4 +82,55 @@ class SessionKtTest { ) assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl") } + + @Test + fun `ExternalSession toSessionData compute the expected result`() { + val result = anExternalSession().toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + ) + assertThat(result.userId).isEqualTo(A_USER_ID.value) + assertThat(result.deviceId).isEqualTo(A_DEVICE_ID.value) + assertThat(result.accessToken).isEqualTo("accessToken") + assertThat(result.refreshToken).isNull() + assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL) + assertThat(result.isTokenValid).isTrue() + assertThat(result.oidcData).isNull() + assertThat(result.slidingSyncProxy).isNull() + assertThat(result.loginType).isEqualTo(LoginType.PASSWORD) + assertThat(result.loginTimestamp).isNotNull() + assertThat(result.passphrase).isEqualTo(A_SECRET) + assertThat(result.sessionPath).isEqualTo("/a/file") + assertThat(result.cachePath).isEqualTo("/a/cache") + } + + @Test + fun `ExternalSession toSessionData can change the validity of the token`() { + val result = anExternalSession().toSessionData( + isTokenValid = false, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + ) + assertThat(result.isTokenValid).isFalse() + } } + +private fun anExternalSession( + userId: String = A_USER_ID.value, + deviceId: String = A_DEVICE_ID.value, + accessToken: String = "accessToken", + refreshToken: String? = null, + homeserverUrl: String = A_HOMESERVER_URL, + slidingSyncProxy: String? = null, + + ) = ExternalSession( + userId = userId, + deviceId = deviceId, + accessToken = accessToken, + refreshToken = refreshToken, + homeserverUrl = homeserverUrl, + slidingSyncProxy = slidingSyncProxy, +) From 6fa585f4c810376bf4793ae4a7730a96dafd7120 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 18:26:36 +0200 Subject: [PATCH 18/25] Add unit test on RustNotificationService And fix mapping error. --- .../api/notification/NotificationData.kt | 6 +- .../api/notification/NotificationService.kt | 3 +- .../libraries/matrix/impl/RustMatrixClient.kt | 2 +- .../impl/notification/NotificationMapper.kt | 13 ++-- .../notification/RustNotificationService.kt | 5 +- ...imelineEventToNotificationContentMapper.kt | 5 +- .../fixtures/factories/NotificationItem.kt | 63 +++++++++++++++++++ .../fixtures/factories/TimelineEventType.kt | 45 +++++++++++++ .../fakes/FakeRustNotificationClient.kt | 10 ++- .../fixtures/fakes/FakeRustTimelineEvent.kt | 25 ++++++++ .../RustNotificationServiceTest.kt | 58 +++++++++++++++++ .../notification/FakeNotificationService.kt | 2 - .../DefaultNotifiableEventResolver.kt | 47 +++++++------- .../DefaultOnMissedCallNotificationHandler.kt | 2 +- .../DefaultNotifiableEventResolverTest.kt | 6 +- 15 files changed, 242 insertions(+), 50 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/TimelineEventType.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEvent.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt index 194d354db9..64fdd74241 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationData.kt @@ -94,7 +94,7 @@ sealed interface NotificationContent { data object RoomHistoryVisibility : StateEvent data object RoomJoinRules : StateEvent data class RoomMemberContent( - val userId: String, + val userId: UserId, val membershipState: RoomMembershipState ) : StateEvent @@ -108,6 +108,10 @@ sealed interface NotificationContent { data object SpaceChild : StateEvent data object SpaceParent : StateEvent } + + data class Invite( + val senderId: UserId, + ) : NotificationContent } enum class CallNotifyType { diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt index 343b73a123..d3f6a6b5ae 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/notification/NotificationService.kt @@ -9,8 +9,7 @@ package io.element.android.libraries.matrix.api.notification import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SessionId interface NotificationService { - suspend fun getNotification(userId: SessionId, roomId: RoomId, eventId: EventId): Result + suspend fun getNotification(roomId: RoomId, eventId: EventId): Result } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index c8e1e93eb4..b47ac6fdc7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -140,7 +140,7 @@ class RustMatrixClient( ) private val notificationProcessSetup = NotificationProcessSetup.SingleProcess(syncService) private val notificationClient = runBlocking { client.notificationClient(notificationProcessSetup) } - private val notificationService = RustNotificationService(sessionId, notificationClient, dispatchers, clock) + private val notificationService = RustNotificationService(notificationClient, dispatchers, clock) private val notificationSettingsService = RustNotificationSettingsService(client, dispatchers) .apply { start() } private val encryptionService = RustEncryptionService( diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt index 7f5dd9bc16..009da11e49 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/NotificationMapper.kt @@ -10,10 +10,9 @@ package io.element.android.libraries.matrix.impl.notification import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData -import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.room.isDm import io.element.android.services.toolbox.api.systemclock.SystemClock import org.matrix.rustcomponents.sdk.NotificationEvent @@ -21,10 +20,9 @@ import org.matrix.rustcomponents.sdk.NotificationItem import org.matrix.rustcomponents.sdk.use class NotificationMapper( - sessionId: SessionId, private val clock: SystemClock, ) { - private val notificationContentMapper = NotificationContentMapper(sessionId) + private val notificationContentMapper = NotificationContentMapper() fun map( eventId: EventId, @@ -56,15 +54,14 @@ class NotificationMapper( } } -class NotificationContentMapper(private val sessionId: SessionId) { +class NotificationContentMapper { private val timelineEventToNotificationContentMapper = TimelineEventToNotificationContentMapper() fun map(notificationEvent: NotificationEvent): NotificationContent = when (notificationEvent) { is NotificationEvent.Timeline -> timelineEventToNotificationContentMapper.map(notificationEvent.event) - is NotificationEvent.Invite -> NotificationContent.StateEvent.RoomMemberContent( - userId = sessionId.value, - membershipState = RoomMembershipState.INVITE, + is NotificationEvent.Invite -> NotificationContent.Invite( + senderId = UserId(notificationEvent.sender), ) } } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt index 7587c092d2..8ed054ac00 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationService.kt @@ -10,7 +10,6 @@ package io.element.android.libraries.matrix.impl.notification import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.notification.NotificationService import io.element.android.services.toolbox.api.systemclock.SystemClock @@ -19,15 +18,13 @@ import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.use class RustNotificationService( - sessionId: SessionId, private val notificationClient: NotificationClient, private val dispatchers: CoroutineDispatchers, clock: SystemClock, ) : NotificationService { - private val notificationMapper: NotificationMapper = NotificationMapper(sessionId, clock) + private val notificationMapper: NotificationMapper = NotificationMapper(clock) override suspend fun getNotification( - userId: SessionId, roomId: RoomId, eventId: EventId, ): Result = withContext(dispatchers.io) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt index 0dccf90fa9..84a187a133 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/notification/TimelineEventToNotificationContentMapper.kt @@ -51,7 +51,10 @@ private fun StateEventContent.toContent(): NotificationContent.StateEvent { StateEventContent.RoomHistoryVisibility -> NotificationContent.StateEvent.RoomHistoryVisibility StateEventContent.RoomJoinRules -> NotificationContent.StateEvent.RoomJoinRules is StateEventContent.RoomMemberContent -> { - NotificationContent.StateEvent.RoomMemberContent(userId, RoomMemberMapper.mapMembership(membershipState)) + NotificationContent.StateEvent.RoomMemberContent( + userId = UserId(userId), + membershipState = RoomMemberMapper.mapMembership(membershipState), + ) } StateEventContent.RoomName -> NotificationContent.StateEvent.RoomName StateEventContent.RoomPinnedEvents -> NotificationContent.StateEvent.RoomPinnedEvents diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt new file mode 100644 index 0000000000..e50e086f63 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/NotificationItem.kt @@ -0,0 +1,63 @@ +/* + * 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.fixtures.factories + +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineEvent +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import io.element.android.libraries.matrix.test.A_USER_NAME +import org.matrix.rustcomponents.sdk.NotificationEvent +import org.matrix.rustcomponents.sdk.NotificationItem +import org.matrix.rustcomponents.sdk.NotificationRoomInfo +import org.matrix.rustcomponents.sdk.NotificationSenderInfo +import org.matrix.rustcomponents.sdk.TimelineEvent + +fun aRustNotificationItem( + event: NotificationEvent = aRustNotificationEventTimeline(), + senderInfo: NotificationSenderInfo = aRustNotificationSenderInfo(), + roomInfo: NotificationRoomInfo = aRustNotificationRoomInfo(), + isNoisy: Boolean? = false, + hasMention: Boolean? = false, +) = NotificationItem( + event = event, + senderInfo = senderInfo, + roomInfo = roomInfo, + isNoisy = isNoisy, + hasMention = hasMention, +) + +fun aRustNotificationSenderInfo( + displayName: String? = A_USER_NAME, + avatarUrl: String? = null, + isNameAmbiguous: Boolean = false, +) = NotificationSenderInfo( + displayName = displayName, + avatarUrl = avatarUrl, + isNameAmbiguous = isNameAmbiguous, +) + +fun aRustNotificationRoomInfo( + displayName: String = A_ROOM_NAME, + avatarUrl: String? = null, + canonicalAlias: String? = null, + joinedMembersCount: ULong = 2u, + isEncrypted: Boolean? = true, + isDirect: Boolean = false, +) = NotificationRoomInfo( + displayName = displayName, + avatarUrl = avatarUrl, + canonicalAlias = canonicalAlias, + joinedMembersCount = joinedMembersCount, + isEncrypted = isEncrypted, + isDirect = isDirect, +) + +fun aRustNotificationEventTimeline( + event: TimelineEvent = FakeRustTimelineEvent(), +) = NotificationEvent.Timeline( + event = event, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/TimelineEventType.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/TimelineEventType.kt new file mode 100644 index 0000000000..ddd74714eb --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/TimelineEventType.kt @@ -0,0 +1,45 @@ +/* + * 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.fixtures.factories + +import io.element.android.libraries.matrix.test.A_MESSAGE +import org.matrix.rustcomponents.sdk.FormattedBody +import org.matrix.rustcomponents.sdk.MessageLikeEventContent +import org.matrix.rustcomponents.sdk.MessageType +import org.matrix.rustcomponents.sdk.TextMessageContent +import org.matrix.rustcomponents.sdk.TimelineEventType + +fun aRustTimelineEventTypeMessageLike( + content: MessageLikeEventContent = aRustMessageLikeEventContentRoomMessage(), +): TimelineEventType.MessageLike { + return TimelineEventType.MessageLike( + content = content, + ) +} + +fun aRustMessageLikeEventContentRoomMessage( + messageType: MessageType = aRustMessageTypeText(), + inReplyToEventId: String? = null, +) = MessageLikeEventContent.RoomMessage( + messageType = messageType, + inReplyToEventId = inReplyToEventId, +) + +fun aRustMessageTypeText( + content: TextMessageContent = aRustTextMessageContent(), +) = MessageType.Text( + content = content, +) + +fun aRustTextMessageContent( + body: String = A_MESSAGE, + formatted: FormattedBody? = null, +) = TextMessageContent( + body = body, + formatted = formatted, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt index 477913d127..7f5583fc18 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationClient.kt @@ -7,7 +7,15 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes +import io.element.android.tests.testutils.simulateLongTask import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.NotificationClient +import org.matrix.rustcomponents.sdk.NotificationItem -class FakeRustNotificationClient : NotificationClient(NoPointer) +class FakeRustNotificationClient( + var notificationItemResult: NotificationItem? = null +) : NotificationClient(NoPointer) { + override suspend fun getNotification(roomId: String, eventId: String): NotificationItem? = simulateLongTask { + notificationItemResult + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEvent.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEvent.kt new file mode 100644 index 0000000000..03611354b7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineEvent.kt @@ -0,0 +1,25 @@ +/* + * 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.fixtures.fakes + +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustTimelineEventTypeMessageLike +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.TimelineEvent +import org.matrix.rustcomponents.sdk.TimelineEventType + +class FakeRustTimelineEvent( + val timestamp: ULong = A_FAKE_TIMESTAMP.toULong(), + val timelineEventType: TimelineEventType = aRustTimelineEventTypeMessageLike(), + val senderId: String = A_USER_ID_2.value, +) : TimelineEvent(NoPointer) { + override fun timestamp(): ULong = timestamp + override fun eventType(): TimelineEventType = timelineEventType + override fun senderId(): String = senderId +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt new file mode 100644 index 0000000000..95ceccbec7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notification/RustNotificationServiceTest.kt @@ -0,0 +1,58 @@ +/* + * 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.notification + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.notification.NotificationContent +import io.element.android.libraries.matrix.api.timeline.item.event.TextMessageType +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustNotificationItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustNotificationClient +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_MESSAGE +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.services.toolbox.api.systemclock.SystemClock +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.NotificationClient + +class RustNotificationServiceTest { + @Test + fun test() = runTest { + val notificationClient = FakeRustNotificationClient( + notificationItemResult = aRustNotificationItem(), + ) + val sut = createRustNotificationService( + notificationClient = notificationClient, + ) + val result = sut.getNotification(A_ROOM_ID, AN_EVENT_ID).getOrThrow()!! + assertThat(result.isEncrypted).isTrue() + assertThat(result.content).isEqualTo( + NotificationContent.MessageLike.RoomMessage( + senderId = A_USER_ID_2, + messageType = TextMessageType( + body = A_MESSAGE, + formatted = null, + ) + ) + ) + } + + private fun TestScope.createRustNotificationService( + notificationClient: NotificationClient = FakeRustNotificationClient(), + clock: SystemClock = FakeSystemClock(), + ) = + RustNotificationService( + notificationClient = notificationClient, + dispatchers = testCoroutineDispatchers(), + clock = clock, + ) +} diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt index 1ea2601e03..a852a2891d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/notification/FakeNotificationService.kt @@ -9,7 +9,6 @@ package io.element.android.libraries.matrix.test.notification import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.notification.NotificationService @@ -21,7 +20,6 @@ class FakeNotificationService : NotificationService { } override suspend fun getNotification( - userId: SessionId, roomId: RoomId, eventId: EventId, ): Result { diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt index 5a352aeb9b..19f9e1f356 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolver.kt @@ -24,7 +24,6 @@ import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.notification.NotificationContent import io.element.android.libraries.matrix.api.notification.NotificationData import io.element.android.libraries.matrix.api.permalink.PermalinkParser -import io.element.android.libraries.matrix.api.room.RoomMembershipState import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType import io.element.android.libraries.matrix.api.timeline.item.event.EventType @@ -76,7 +75,6 @@ class DefaultNotifiableEventResolver @Inject constructor( val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null val notificationService = client.notificationService() val notificationData = notificationService.getNotification( - userId = sessionId, roomId = roomId, eventId = eventId, ).onFailure { @@ -113,30 +111,26 @@ class DefaultNotifiableEventResolver @Inject constructor( hasMentionOrReply = hasMention, ) } - is NotificationContent.StateEvent.RoomMemberContent -> { - if (content.membershipState == RoomMembershipState.INVITE) { - InviteNotifiableEvent( - sessionId = userId, - roomId = roomId, - eventId = eventId, - editedEventId = null, - canBeReplaced = true, - roomName = roomDisplayName, - noisy = isNoisy, - timestamp = this.timestamp, - soundName = null, - isRedacted = false, - isUpdated = false, - description = descriptionFromRoomMembershipInvite(isDirect), - // TODO check if type is needed anymore - type = null, - // TODO check if title is needed anymore - title = null, - ) - } else { - Timber.tag(loggerTag.value).d("Ignoring notification state event for membership ${content.membershipState}") - null - } + is NotificationContent.Invite -> { + InviteNotifiableEvent( + sessionId = userId, + roomId = roomId, + eventId = eventId, + editedEventId = null, + canBeReplaced = true, + roomName = roomDisplayName, + noisy = isNoisy, + timestamp = this.timestamp, + soundName = null, + isRedacted = false, + isUpdated = false, + // TODO We could use the senderId here + description = descriptionFromRoomMembershipInvite(isDirect), + // TODO check if type is needed anymore + type = null, + // TODO check if title is needed anymore + title = null, + ) } NotificationContent.MessageLike.CallAnswer, NotificationContent.MessageLike.CallCandidates, @@ -203,6 +197,7 @@ class DefaultNotifiableEventResolver @Inject constructor( NotificationContent.MessageLike.Sticker -> null.also { Timber.tag(loggerTag.value).d("Ignoring notification for sticker") } + is NotificationContent.StateEvent.RoomMemberContent, NotificationContent.StateEvent.PolicyRuleRoom, NotificationContent.StateEvent.PolicyRuleServer, NotificationContent.StateEvent.PolicyRuleUser, diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandler.kt index 09b6810775..a976fff18e 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/DefaultOnMissedCallNotificationHandler.kt @@ -30,7 +30,7 @@ class DefaultOnMissedCallNotificationHandler @Inject constructor( // Resolve the event and add a notification for it, at this point it should no longer be a ringing one val notificationData = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?.notificationService() - ?.getNotification(sessionId, roomId, eventId) + ?.getNotification(roomId, eventId) ?.getOrNull() ?: return diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 240802d98c..baf6c53c79 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -370,7 +370,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - userId = A_USER_ID_2.value, + sender = A_USER_ID_2, membershipState = RoomMembershipState.INVITE ), isDirect = false, @@ -405,7 +405,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - userId = A_USER_ID_2.value, + sender = A_USER_ID_2, membershipState = RoomMembershipState.INVITE ), isDirect = true, @@ -440,7 +440,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - userId = A_USER_ID_2.value, + sender = A_USER_ID_2, membershipState = RoomMembershipState.JOIN ) ) From f209eb27ac0ee503ca757123b77721e0b8009ce1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 19:55:27 +0200 Subject: [PATCH 19/25] Add test on RustNotificationSettingsService --- .../factories/RoomNotificationSettings.kt | 19 +++++++++ .../fakes/FakeRustNotificationSettings.kt | 13 +++++- .../RustNotificationSettingsServiceTest.kt | 42 +++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomNotificationSettings.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomNotificationSettings.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomNotificationSettings.kt new file mode 100644 index 0000000000..6324b28811 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomNotificationSettings.kt @@ -0,0 +1,19 @@ +/* + * 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.fixtures.factories + +import org.matrix.rustcomponents.sdk.RoomNotificationMode +import org.matrix.rustcomponents.sdk.RoomNotificationSettings + +fun aRustRoomNotificationSettings( + mode: RoomNotificationMode = RoomNotificationMode.ALL_MESSAGES, + isDefault: Boolean = true, +) = RoomNotificationSettings( + mode = mode, + isDefault = isDefault +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt index a889530cb2..4b0acbfc08 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt @@ -7,14 +7,25 @@ package io.element.android.libraries.matrix.impl.fixtures.fakes +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomNotificationSettings import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.NotificationSettings import org.matrix.rustcomponents.sdk.NotificationSettingsDelegate +import org.matrix.rustcomponents.sdk.RoomNotificationSettings -class FakeRustNotificationSettings : NotificationSettings(NoPointer) { +class FakeRustNotificationSettings( + private val roomNotificationSettings: RoomNotificationSettings = aRustRoomNotificationSettings(), +) : NotificationSettings(NoPointer) { private var delegate: NotificationSettingsDelegate? = null override fun setDelegate(delegate: NotificationSettingsDelegate?) { this.delegate = delegate } + + override suspend fun getRoomNotificationSettings( + roomId: String, + isEncrypted: Boolean, + isOneToOne: Boolean, + ): RoomNotificationSettings = roomNotificationSettings } + diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt new file mode 100644 index 0000000000..01b2c1f3ab --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/notificationsettings/RustNotificationSettingsServiceTest.kt @@ -0,0 +1,42 @@ +/* + * 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.notificationsettings + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClient +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustNotificationSettings +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.NotificationSettings + +class RustNotificationSettingsServiceTest { + @Test + fun test() = runTest { + val sut = createRustNotificationSettingsService() + val result = sut.getRoomNotificationSettings( + roomId = A_ROOM_ID, + isEncrypted = true, + isOneToOne = true, + ).getOrNull()!! + assertThat(result.mode).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + assertThat(result.isDefault).isTrue() + } + + private fun TestScope.createRustNotificationSettingsService( + notificationSettings: NotificationSettings = FakeRustNotificationSettings(), + ) = RustNotificationSettingsService( + client = FakeRustClient( + notificationSettings = notificationSettings, + ), + dispatchers = testCoroutineDispatchers(), + ) +} From 8439c104fe9003d106449a9f19f8a29ace3562e7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 19:57:52 +0200 Subject: [PATCH 20/25] Add test on AccountManagementAction.toRustAction() --- .../oidc/AccountManagementActionKtTest.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt new file mode 100644 index 0000000000..dc18443ada --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/oidc/AccountManagementActionKtTest.kt @@ -0,0 +1,28 @@ +/* + * 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.oidc + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.oidc.AccountManagementAction +import io.element.android.libraries.matrix.test.A_DEVICE_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.AccountManagementAction as RustAccountManagementAction + +class AccountManagementActionKtTest { + @Test + fun `test AccountManagementAction to RustAccountManagementAction`() { + assertThat(AccountManagementAction.Profile.toRustAction()) + .isEqualTo(RustAccountManagementAction.Profile) + assertThat(AccountManagementAction.SessionEnd(A_DEVICE_ID).toRustAction()) + .isEqualTo(RustAccountManagementAction.SessionEnd(A_DEVICE_ID.value)) + assertThat(AccountManagementAction.SessionView(A_DEVICE_ID).toRustAction()) + .isEqualTo(RustAccountManagementAction.SessionView(A_DEVICE_ID.value)) + assertThat(AccountManagementAction.SessionsList.toRustAction()) + .isEqualTo(RustAccountManagementAction.SessionsList) + } +} From 98cfa25d5bafb98fc366333fde898f5d1de47a21 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 20:08:07 +0200 Subject: [PATCH 21/25] Add test on RustPushersService --- .../impl/fixtures/fakes/FakeRustClient.kt | 12 ++++ .../impl/pushers/RustPushersServiceTest.kt | 67 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt index 935537a27f..740d354821 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustClient.kt @@ -17,6 +17,8 @@ import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.NotificationClient import org.matrix.rustcomponents.sdk.NotificationProcessSetup import org.matrix.rustcomponents.sdk.NotificationSettings +import org.matrix.rustcomponents.sdk.PusherIdentifiers +import org.matrix.rustcomponents.sdk.PusherKind import org.matrix.rustcomponents.sdk.RoomDirectorySearch import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SyncServiceBuilder @@ -41,4 +43,14 @@ class FakeRustClient( override suspend fun restoreSession(session: Session) = Unit override fun syncService(): SyncServiceBuilder = FakeRustSyncServiceBuilder() override fun roomDirectorySearch(): RoomDirectorySearch = FakeRoomDirectorySearch() + override suspend fun setPusher( + identifiers: PusherIdentifiers, + kind: PusherKind, + appDisplayName: String, + deviceDisplayName: String, + profileTag: String?, + lang: String, + ) = Unit + + override suspend fun deletePusher(identifiers: PusherIdentifiers) = Unit } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt new file mode 100644 index 0000000000..34821b935a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/pushers/RustPushersServiceTest.kt @@ -0,0 +1,67 @@ +/* + * 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.pushers + +import io.element.android.libraries.matrix.api.pusher.SetHttpPusherData +import io.element.android.libraries.matrix.api.pusher.UnsetHttpPusherData +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClient +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class RustPushersServiceTest { + @Test + fun `setPusher should invoke the client method`() = runTest { + val sut = RustPushersService( + client = FakeRustClient(), + dispatchers = testCoroutineDispatchers() + ) + sut.setHttpPusher( + setHttpPusherData = aSetHttpPusherData() + ).getOrThrow() + } + + @Test + fun `unsetPusher should invoke the client method`() = runTest { + val sut = RustPushersService( + client = FakeRustClient(), + dispatchers = testCoroutineDispatchers() + ) + sut.unsetHttpPusher( + unsetHttpPusherData = aUnsetHttpPusherData(), + ).getOrThrow() + } +} + +private fun aSetHttpPusherData( + pushKey: String = "pushKey", + appId: String = "appId", + url: String = "url", + defaultPayload: String = "defaultPayload", + appDisplayName: String = "appDisplayName", + deviceDisplayName: String = "deviceDisplayName", + profileTag: String = "profileTag", + lang: String = "lang", +) = SetHttpPusherData( + pushKey = pushKey, + appId = appId, + url = url, + defaultPayload = defaultPayload, + appDisplayName = appDisplayName, + deviceDisplayName = deviceDisplayName, + profileTag = profileTag, + lang = lang +) + +private fun aUnsetHttpPusherData( + pushKey: String = "pushKey", + appId: String = "appId", +) = UnsetHttpPusherData( + pushKey = pushKey, + appId = appId, +) From 8c5e682f1be6e4886be992607212d73f777015dc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 20:14:58 +0200 Subject: [PATCH 22/25] Cleanup --- .../matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt | 1 - .../matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt | 1 - .../matrix/impl/fixtures/fakes/FakeRustRoomListService.kt | 1 - .../android/libraries/matrix/impl/mapper/SessionKtTest.kt | 3 +-- .../impl/roomdirectory/RoomDirectorySearchProcessorTest.kt | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt index 2a3cadd045..4975be883f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationServiceTest.kt @@ -54,4 +54,3 @@ class RustMatrixAuthenticationServiceTest { ) } } - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt index 4b0acbfc08..be2138fb44 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustNotificationSettings.kt @@ -28,4 +28,3 @@ class FakeRustNotificationSettings( isOneToOne: Boolean, ): RoomNotificationSettings = roomNotificationSettings } - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt index 69ef9a4781..f2baa2b6a5 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListService.kt @@ -15,7 +15,6 @@ import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicatorListener import org.matrix.rustcomponents.sdk.TaskHandle class FakeRustRoomListService : RoomListService(NoPointer) { - override suspend fun allRooms(): RoomList { return FakeRustRoomList() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt index b0e1254179..9b50ef700d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -125,8 +125,7 @@ private fun anExternalSession( refreshToken: String? = null, homeserverUrl: String = A_HOMESERVER_URL, slidingSyncProxy: String? = null, - - ) = ExternalSession( +) = ExternalSession( userId = userId, deviceId = deviceId, accessToken = accessToken, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt index be61bd77f2..4ea38438fe 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDirectorySearchProcessorTest.kt @@ -69,7 +69,6 @@ class RoomDirectorySearchProcessorTest { ) ) assertThat(awaitItem()).isEqualTo(listOf(room1, room2, room3)) - } } } From b3af1f8b52ef74206f2f49690fe18394c57559c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 20:32:22 +0200 Subject: [PATCH 23/25] Fix compilation issue. --- .../kotlin/io/element/android/samples/minimal/MainActivity.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt index 6e912b513a..efaecb0762 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/MainActivity.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.core.view.WindowCompat import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService +import io.element.android.libraries.matrix.impl.RustClientBuilderProvider import io.element.android.libraries.matrix.impl.RustMatrixClientFactory import io.element.android.libraries.matrix.impl.analytics.UtdTracker import io.element.android.libraries.matrix.impl.auth.OidcConfigurationProvider @@ -57,7 +58,8 @@ class MainActivity : ComponentActivity() { clock = DefaultSystemClock(), utdTracker = UtdTracker(NoopAnalyticsService()), featureFlagService = AlwaysEnabledFeatureFlagService(), - timelineEventTypeFilterFactory = RustTimelineEventTypeFilterFactory() + timelineEventTypeFilterFactory = RustTimelineEventTypeFilterFactory(), + clientBuilderProvider = RustClientBuilderProvider(), ), passphraseGenerator = NullPassphraseGenerator(), oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory), From 1a9fe939ef4df47f97f89b4b048457c440874453 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 20 Sep 2024 09:07:23 +0200 Subject: [PATCH 24/25] Fix test compilation issue. --- .../notifications/DefaultNotifiableEventResolverTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index baf6c53c79..6e3cfb8091 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -370,7 +370,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - sender = A_USER_ID_2, + userId = A_USER_ID_2, membershipState = RoomMembershipState.INVITE ), isDirect = false, @@ -405,7 +405,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - sender = A_USER_ID_2, + userId = A_USER_ID_2, membershipState = RoomMembershipState.INVITE ), isDirect = true, @@ -440,7 +440,7 @@ class DefaultNotifiableEventResolverTest { notificationResult = Result.success( createNotificationData( content = NotificationContent.StateEvent.RoomMemberContent( - sender = A_USER_ID_2, + userId = A_USER_ID_2, membershipState = RoomMembershipState.JOIN ) ) From 88a30eb3219a700047b243a1aa8753117e0172c7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 20 Sep 2024 09:14:55 +0200 Subject: [PATCH 25/25] Fix DefaultNotifiableEventResolverTest tests. --- .../DefaultNotifiableEventResolverTest.kt | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt index 6e3cfb8091..e41d26b943 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultNotifiableEventResolverTest.kt @@ -378,6 +378,22 @@ class DefaultNotifiableEventResolverTest { ) ) val result = sut.resolveEvent(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID) + assertThat(result).isNull() + } + + @Test + fun `resolve invite room`() = runTest { + val sut = createDefaultNotifiableEventResolver( + notificationResult = Result.success( + createNotificationData( + content = NotificationContent.Invite( + senderId = A_USER_ID_2, + ), + isDirect = false, + ) + ) + ) + val result = sut.resolveEvent(A_SESSION_ID, A_ROOM_ID, AN_EVENT_ID) val expectedResult = ResolvedPushEvent.Event( InviteNotifiableEvent( sessionId = A_SESSION_ID, @@ -400,13 +416,12 @@ class DefaultNotifiableEventResolverTest { } @Test - fun `resolve RoomMemberContent invite direct`() = runTest { + fun `resolve invite invite direct`() = runTest { val sut = createDefaultNotifiableEventResolver( notificationResult = Result.success( createNotificationData( - content = NotificationContent.StateEvent.RoomMemberContent( - userId = A_USER_ID_2, - membershipState = RoomMembershipState.INVITE + content = NotificationContent.Invite( + senderId = A_USER_ID_2, ), isDirect = true, )