From cbb5e0ffed3be44d5b6047ca4a2e92779979fc8c Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 17 Sep 2024 16:17:08 +0200 Subject: [PATCH 01/56] Resolve send failure verification : fix crash when dismissing. --- .../resolve/ResolveVerifiedUserSendFailureView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index 4c1d40cc87..e0d964fa51 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -118,7 +118,7 @@ private fun VerifiedUserSendFailure.title(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName ) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } @@ -134,7 +134,7 @@ private fun VerifiedUserSendFailure.subtitle(): String { id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName ) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } @@ -143,7 +143,7 @@ private fun VerifiedUserSendFailure.resolveAction(): String { return when (this) { is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_primary_button_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource(id = CommonStrings.screen_resolve_send_failure_changed_identity_primary_button_title) - VerifiedUserSendFailure.None -> error("This method should never be called for this state") + VerifiedUserSendFailure.None -> "" } } From 4bd7fbe2b004e6b637830fc571c70d7c1373a0c7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 20:06:10 +0200 Subject: [PATCH 02/56] version++ --- plugins/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/src/main/kotlin/Versions.kt b/plugins/src/main/kotlin/Versions.kt index c2e6f2d5c3..54afab0525 100644 --- a/plugins/src/main/kotlin/Versions.kt +++ b/plugins/src/main/kotlin/Versions.kt @@ -47,7 +47,7 @@ private const val versionMinor = 6 // Note: even values are reserved for regular release, odd values for hotfix release. // When creating a hotfix, you should decrease the value, since the current value // is the value for the next regular release. -private const val versionPatch = 2 +private const val versionPatch = 3 object Versions { val versionCode = 4_000_000 + versionMajor * 1_00_00 + versionMinor * 1_00 + versionPatch From dbc4c8f56ed5a6f31b9f5d70742e3dc7082a40d1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 20:33:16 +0200 Subject: [PATCH 03/56] Changelog for version 0.6.2 --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index e4215c9fda..a3b77c6ec6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +Changes in Element X v0.6.2 (2024-09-17) +======================================== + +### ✨ Features +* Account deactivation. by @bmarty in https://github.com/element-hq/element-x-android/pull/3479 + Changes in Element X v0.6.1 (2024-09-17) ======================================== From 5e3def8185157943f3395f74c90cec6cfbacba86 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 17 Sep 2024 21:17:04 +0200 Subject: [PATCH 04/56] Add tests on AccountDeactivationView --- features/deactivation/impl/build.gradle.kts | 1 + .../logout/impl/AccountDeactivationView.kt | 3 + .../impl/AccountDeactivationViewTest.kt | 102 +++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/features/deactivation/impl/build.gradle.kts b/features/deactivation/impl/build.gradle.kts index 6e19a485d4..25a71098ac 100644 --- a/features/deactivation/impl/build.gradle.kts +++ b/features/deactivation/impl/build.gradle.kts @@ -33,6 +33,7 @@ dependencies { implementation(projects.libraries.architecture) implementation(projects.libraries.matrix.api) implementation(projects.libraries.designsystem) + implementation(projects.libraries.testtags) implementation(projects.libraries.uiStrings) api(projects.features.deactivation.api) diff --git a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt index ec397393bb..7df20acb96 100644 --- a/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt +++ b/features/deactivation/impl/src/main/kotlin/io/element/android/features/logout/impl/AccountDeactivationView.kt @@ -65,6 +65,8 @@ import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.theme.components.autofill import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.testtags.testTag import io.element.android.libraries.ui.strings.CommonStrings import kotlinx.collections.immutable.persistentListOf @@ -277,6 +279,7 @@ private fun Content( .padding(top = 8.dp) .fillMaxWidth() .onTabOrEnterKeyFocusNext(focusManager) + .testTag(TestTags.loginPassword) .autofill( autofillTypes = listOf(AutofillType.Password), onFill = { diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt index 97a1b34751..06d27e463b 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationViewTest.kt @@ -10,15 +10,26 @@ package io.element.android.features.logout.impl import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.performTextInput import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.element.android.features.deactivation.impl.R +import io.element.android.libraries.architecture.AsyncAction +import io.element.android.libraries.matrix.test.AN_EXCEPTION +import io.element.android.libraries.matrix.test.A_PASSWORD +import io.element.android.libraries.testtags.TestTags +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder +import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.ensureCalledOnce import io.element.android.tests.testutils.pressBack +import io.element.android.tests.testutils.pressTag import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule import org.junit.runner.RunWith +import org.robolectric.annotation.Config @RunWith(AndroidJUnit4::class) class AccountDeactivationViewTest { @@ -36,7 +47,96 @@ class AccountDeactivationViewTest { } } - // TODO Add more tests + @Config(qualifiers = "h1024dp") + @Test + fun `clicking on Deactivate emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(CommonStrings.action_deactivate) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) + } + + @Test + fun `clicking on Deactivate on the confirmation dialog emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + accountDeactivationAction = AsyncAction.Confirming, + eventSink = eventsRecorder, + ), + ) + rule.pressTag(TestTags.dialogPositive.value) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(false)) + } + + @Test + fun `clicking on retry on the confirmation dialog emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + accountDeactivationAction = AsyncAction.Failure(AN_EXCEPTION), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(CommonStrings.action_retry) + eventsRecorder.assertSingle(AccountDeactivationEvents.DeactivateAccount(true)) + } + + @Test + fun `switching on the erase all switch emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + eventSink = eventsRecorder, + ), + ) + rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(true)) + } + + @Test + fun `switching off the erase all switch emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + eraseData = true, + ), + eventSink = eventsRecorder, + ), + ) + rule.clickOn(R.string.screen_deactivate_account_delete_all_messages) + eventsRecorder.assertSingle(AccountDeactivationEvents.SetEraseData(false)) + } + + @Config(qualifiers = "h1024dp") + @Test + fun `typing text in the password field emits the expected Event`() { + val eventsRecorder = EventsRecorder() + rule.setAccountDeactivationView( + state = anAccountDeactivationState( + deactivateFormState = aDeactivateFormState( + password = A_PASSWORD, + ), + eventSink = eventsRecorder, + ), + ) + rule.onNodeWithTag(TestTags.loginPassword.value).performTextInput("A") + eventsRecorder.assertSingle(AccountDeactivationEvents.SetPassword("A$A_PASSWORD")) + } } private fun AndroidComposeTestRule.setAccountDeactivationView( From 52405553293bf1b67a9efb848936a0e5e44d085a Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 11:07:07 +0200 Subject: [PATCH 05/56] Resolve send failure verification : clearer message when unsigned device is from you --- .../messages/impl/actionlist/ActionListView.kt | 3 ++- .../crypto/sendfailure/VerifiedUserSendFailure.kt | 7 ++++--- .../sendfailure/VerifiedUserSendFailureFactory.kt | 8 ++++++-- .../ResolveVerifiedUserSendFailureStateProvider.kt | 2 +- .../resolve/ResolveVerifiedUserSendFailureView.kt | 9 +++++++-- .../ResolveVerifiedUserSendFailurePresenterTest.kt | 12 ++++++------ .../ui-strings/src/main/res/values/localazy.xml | 3 +++ 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 8c950012db..a81975bf46 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -374,7 +374,8 @@ private fun VerifiedUserSendFailureView( fun VerifiedUserSendFailure.headline(): String { return when (this) { is None -> "" - is UnsignedDevice -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromOther -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_unsigned_device, userDisplayName) + is UnsignedDevice.FromYou -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_you_unsigned_device) is ChangedIdentity -> stringResource(CommonStrings.screen_timeline_item_menu_send_failure_changed_identity, userDisplayName) } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt index e3c798f7df..13a26a8bdb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailure.kt @@ -13,9 +13,10 @@ import androidx.compose.runtime.Immutable sealed interface VerifiedUserSendFailure { data object None : VerifiedUserSendFailure - data class UnsignedDevice( - val userDisplayName: String, - ) : VerifiedUserSendFailure + sealed interface UnsignedDevice : VerifiedUserSendFailure { + data object FromYou : UnsignedDevice + data class FromOther(val userDisplayName: String) : UnsignedDevice + } data class ChangedIdentity( val userDisplayName: String, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt index de5817c909..b96baed27d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/VerifiedUserSendFailureFactory.kt @@ -23,8 +23,12 @@ class VerifiedUserSendFailureFactory @Inject constructor( if (userId == null) { VerifiedUserSendFailure.None } else { - val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value - VerifiedUserSendFailure.UnsignedDevice(displayName) + if (userId == room.sessionId) { + VerifiedUserSendFailure.UnsignedDevice.FromYou + } else { + val displayName = room.userDisplayName(userId).getOrNull() ?: userId.value + VerifiedUserSendFailure.UnsignedDevice.FromOther(displayName) + } } } is LocalEventSendState.Failed.VerifiedUserChangedIdentity -> { diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt index 1f8335b648..cdbdf6fcb0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureStateProvider.kt @@ -36,7 +36,7 @@ fun aResolveVerifiedUserSendFailureState( eventSink = eventSink ) -fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice( +fun anUnsignedDeviceSendFailure(userDisplayName: String = "Alice") = VerifiedUserSendFailure.UnsignedDevice.FromOther( userDisplayName = userDisplayName, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt index e0d964fa51..fb602fa943 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailureView.kt @@ -113,7 +113,11 @@ fun ResolveVerifiedUserSendFailureView( @Composable private fun VerifiedUserSendFailure.title(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource(id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, userDisplayName) + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( + id = CommonStrings.screen_resolve_send_failure_unsigned_device_title, + userDisplayName + ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_title) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_title, userDisplayName @@ -125,11 +129,12 @@ private fun VerifiedUserSendFailure.title(): String { @Composable private fun VerifiedUserSendFailure.subtitle(): String { return when (this) { - is VerifiedUserSendFailure.UnsignedDevice -> stringResource( + is VerifiedUserSendFailure.UnsignedDevice.FromOther -> stringResource( id = CommonStrings.screen_resolve_send_failure_unsigned_device_subtitle, userDisplayName, userDisplayName, ) + VerifiedUserSendFailure.UnsignedDevice.FromYou -> stringResource(id = CommonStrings.screen_resolve_send_failure_you_unsigned_device_subtitle) is VerifiedUserSendFailure.ChangedIdentity -> stringResource( id = CommonStrings.screen_resolve_send_failure_changed_identity_subtitle, userDisplayName diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt index 8d5884cf08..e74ae89b4f 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/crypto/sendfailure/resolve/ResolveVerifiedUserSendFailurePresenterTest.kt @@ -94,7 +94,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { initialState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(failedMessage)) skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Dismiss) } skipItems(1) @@ -124,7 +124,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.Retry) } awaitItem().also { state -> @@ -158,7 +158,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> @@ -167,7 +167,7 @@ class ResolveVerifiedUserSendFailurePresenterTest { // This should move to the next user skipItems(2) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID_2.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromOther(A_USER_ID_2.value)) assertThat(state.resolveAction).isEqualTo(AsyncAction.Success(Unit)) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } @@ -199,14 +199,14 @@ class ResolveVerifiedUserSendFailurePresenterTest { skipItems(1) awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) state.eventSink(ResolveVerifiedUserSendFailureEvents.ResolveAndResend) } awaitItem().also { state -> assertThat(state.resolveAction).isEqualTo(AsyncAction.Loading) } awaitItem().also { state -> - assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice(A_USER_ID.value)) + assertThat(state.verifiedUserSendFailure).isEqualTo(VerifiedUserSendFailure.UnsignedDevice.FromYou) assertThat(state.resolveAction).isInstanceOf(AsyncAction.Failure::class.java) } ensureAllEventsConsumed() diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml index 8e2e7822bf..c71dd4d505 100644 --- a/libraries/ui-strings/src/main/res/values/localazy.xml +++ b/libraries/ui-strings/src/main/res/values/localazy.xml @@ -291,6 +291,8 @@ Reason: %1$s." "Send message anyway" "%1$s is using one or more unverified devices. You can send the message anyway, or you can cancel for now and try again later after %2$s has verified all their devices." "Your message was not sent because %1$s has not verified all devices" + "One or more of your devices are unverified. You can send the message anyway, or you can cancel for now and try again later after you have verified all of your devices." + "Your message was not sent because you have not verified one or more of your devices" "Pinned messages" "Failed processing media to upload, please try again." "Could not retrieve user details" @@ -314,6 +316,7 @@ Reason: %1$s." "Share this location" "Message not sent because %1$s’s verified identity has changed." "Message not sent because %1$s has not verified all devices." + "Message not sent because you have not verified one or more of your devices." "Location" "Version: %1$s (%2$s)" "en" From 1a049832ab41ba6150641d468adb0255f2eb2d6a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 11:41:15 +0200 Subject: [PATCH 06/56] Distinguish between roomId and roomAlias. --- .../android/libraries/matrix/api/core/MatrixPatterns.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt index 851dd44e3e..454dfba462 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/core/MatrixPatterns.kt @@ -149,7 +149,12 @@ object MatrixPatterns { add(MatrixPatternResult(MatrixPatternType.USER_ID, permalink.userId.toString(), match.range.first, match.range.last + 1)) } is PermalinkData.RoomLink -> { - add(MatrixPatternResult(MatrixPatternType.ROOM_ALIAS, permalink.roomIdOrAlias.identifier, match.range.first, match.range.last + 1)) + when (permalink.roomIdOrAlias) { + is RoomIdOrAlias.Alias -> MatrixPatternType.ROOM_ALIAS + is RoomIdOrAlias.Id -> if (permalink.eventId == null) MatrixPatternType.ROOM_ID else null + }?.let { type -> + add(MatrixPatternResult(type, permalink.roomIdOrAlias.identifier, match.range.first, match.range.last + 1)) + } } else -> Unit } From c08b8c04169a58c772f43e320a49d2f35ad595f3 Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 18 Sep 2024 13:54:54 +0200 Subject: [PATCH 07/56] Make sure the logout action doesn't cause a crash (#3480) * Make sure the logout doesn't cause a crash Some reasons why this could happen: 1. The `ClientDelegate` could receive a `didReceiveAuthError` callback call on a logout, which could trigger another logout when every Rust object had already been destroyed. 2. Even though we stop the sync before logging out, `LoggedInFlowNode` will try to start it again automatically when it detects we still have internet connection. Making sure to unregister the delegate should fix the first part of the issue. For the other one, adding `RustSyncService.isServiceReady` to check if we should start/stop the service, which is enabled by default and set to false on destroy should help. * Apply the same patch on account deactivation. --------- Co-authored-by: Benoit Marty --- .../matrix/impl/RustClientSessionDelegate.kt | 1 - .../libraries/matrix/impl/RustMatrixClient.kt | 44 ++++++++++++------- .../matrix/impl/sync/RustSyncService.kt | 23 +++++++++- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt index 03a59203e5..dcdb719511 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustClientSessionDelegate.kt @@ -50,7 +50,6 @@ class RustClientSessionDelegate( */ fun bindClient(client: RustMatrixClient) { this.client = client - client.setDelegate(this) } override fun saveSessionInKeychain(session: Session) { 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 a5c5f1f442..a49db1ccd2 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 @@ -122,7 +122,7 @@ class RustMatrixClient( private val baseDirectory: File, baseCacheDirectory: File, private val clock: SystemClock, - sessionDelegate: RustClientSessionDelegate, + private val sessionDelegate: RustClientSessionDelegate, ) : MatrixClient { override val sessionId: UserId = UserId(client.userId()) override val deviceId: DeviceId = DeviceId(client.deviceId()) @@ -195,7 +195,7 @@ class RustMatrixClient( private val roomMembershipObserver = RoomMembershipObserver() - private val clientDelegateTaskHandle: TaskHandle? = client.setDelegate(sessionDelegate) + private var clientDelegateTaskHandle: TaskHandle? = client.setDelegate(sessionDelegate) private val _userProfile: MutableStateFlow = MutableStateFlow( MatrixUser( @@ -449,12 +449,12 @@ class RustMatrixClient( override fun close() { appCoroutineScope.launch { roomFactory.destroy() + rustSyncService.destroy() } sessionCoroutineScope.cancel() clientDelegateTaskHandle?.cancelAndDestroy() notificationSettingsService.destroy() verificationService.destroy() - syncService.destroy() innerRoomListService.destroy() notificationClient.destroy() notificationProcessSetup.destroy() @@ -473,7 +473,9 @@ class RustMatrixClient( override suspend fun logout(userInitiated: Boolean, ignoreSdkError: Boolean): String? { var result: String? = null - syncService.stop() + // Remove current delegate so we don't receive an auth error + clientDelegateTaskHandle?.cancelAndDestroy() + clientDelegateTaskHandle = null withContext(sessionDispatcher) { if (userInitiated) { try { @@ -482,12 +484,15 @@ class RustMatrixClient( if (ignoreSdkError) { Timber.e(failure, "Fail to call logout on HS. Still delete local files.") } else { + // If the logout failed we need to restore the delegate + clientDelegateTaskHandle = client.setDelegate(sessionDelegate) Timber.e(failure, "Fail to call logout on HS.") throw failure } } } close() + deleteSessionDirectory(deleteCryptoDb = true) if (userInitiated) { sessionStore.removeSession(sessionId.value) @@ -506,7 +511,9 @@ class RustMatrixClient( override suspend fun deactivateAccount(password: String, eraseData: Boolean): Result = withContext(sessionDispatcher) { Timber.w("Deactivating account") - syncService.stop() + // Remove current delegate so we don't receive an auth error + clientDelegateTaskHandle?.cancelAndDestroy() + clientDelegateTaskHandle = null runCatching { // First call without AuthData, should fail val firstAttempt = runCatching { @@ -518,15 +525,22 @@ class RustMatrixClient( if (firstAttempt.isFailure) { Timber.w(firstAttempt.exceptionOrNull(), "Expected failure, try again") // This is expected, try again with the password - client.deactivateAccount( - authData = AuthData.Password( - passwordDetails = AuthDataPasswordDetails( - identifier = sessionId.value, - password = password, + runCatching { + client.deactivateAccount( + authData = AuthData.Password( + passwordDetails = AuthDataPasswordDetails( + identifier = sessionId.value, + password = password, + ), ), - ), - eraseData = eraseData, - ) + eraseData = eraseData, + ) + }.onFailure { + Timber.e(it, "Failed to deactivate account") + // If the deactivation failed we need to restore the delegate + clientDelegateTaskHandle = client.setDelegate(sessionDelegate) + throw it + } } close() deleteSessionDirectory(deleteCryptoDb = true) @@ -592,10 +606,6 @@ class RustMatrixClient( return client.session().slidingSyncVersion == SlidingSyncVersion.Native } - internal fun setDelegate(delegate: RustClientSessionDelegate) { - client.setDelegate(delegate) - } - private suspend fun File.getCacheSize( includeCryptoDb: Boolean = false, ): Long = withContext(sessionDispatcher) { diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt index cf52609fa0..0a859ee146 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/sync/RustSyncService.kt @@ -16,15 +16,22 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn -import org.matrix.rustcomponents.sdk.SyncServiceInterface import org.matrix.rustcomponents.sdk.SyncServiceState import timber.log.Timber +import java.util.concurrent.atomic.AtomicBoolean +import org.matrix.rustcomponents.sdk.SyncService as InnerSyncService class RustSyncService( - private val innerSyncService: SyncServiceInterface, + private val innerSyncService: InnerSyncService, sessionCoroutineScope: CoroutineScope ) : SyncService { + private val isServiceReady = AtomicBoolean(true) + override suspend fun startSync() = runCatching { + if (!isServiceReady.get()) { + Timber.d("Can't start sync: service is not ready") + return@runCatching + } Timber.i("Start sync") innerSyncService.start() }.onFailure { @@ -32,12 +39,24 @@ class RustSyncService( } override suspend fun stopSync() = runCatching { + if (!isServiceReady.get()) { + Timber.d("Can't stop sync: service is not ready") + return@runCatching + } Timber.i("Stop sync") innerSyncService.stop() }.onFailure { Timber.d("Stop sync failed: $it") } + suspend fun destroy() { + // If the service was still running, stop it + stopSync() + Timber.d("Destroying sync service") + isServiceReady.set(false) + innerSyncService.destroy() + } + override val syncState: StateFlow = innerSyncService.stateFlow() .map(SyncServiceState::toSyncState) From 05f2c71745428e47316713f51416385868c1c0f8 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 14:01:05 +0200 Subject: [PATCH 08/56] Pinned messages : remove debounce now it's properly handled by sdk. --- .../impl/pinned/banner/PinnedMessagesBannerPresenter.kt | 3 --- .../messages/impl/pinned/list/PinnedMessagesListPresenter.kt | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt index 81405c8f38..457e96c5b8 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenter.kt @@ -25,14 +25,12 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import javax.inject.Inject -import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesBannerPresenter @Inject constructor( private val room: MatrixRoom, @@ -123,7 +121,6 @@ class PinnedMessagesBannerPresenter @Inject constructor( is AsyncData.Loading -> flowOf(AsyncData.Loading()) is AsyncData.Success -> { asyncTimeline.data.timelineItems - .debounce(300.milliseconds) .map { timelineItems -> val pinnedItems = timelineItems.mapNotNull { timelineItem -> itemFactory.create(timelineItem) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt index 6c8c52a443..1525a8a5e1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/list/PinnedMessagesListPresenter.kt @@ -43,14 +43,12 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import timber.log.Timber -import kotlin.time.Duration.Companion.milliseconds class PinnedMessagesListPresenter @AssistedInject constructor( @Assisted private val navigator: PinnedMessagesListNavigator, @@ -174,7 +172,7 @@ class PinnedMessagesListPresenter @AssistedInject constructor( is AsyncData.Failure -> flowOf(AsyncData.Failure(asyncTimeline.error)) is AsyncData.Loading -> flowOf(AsyncData.Loading()) is AsyncData.Success -> { - val timelineItemsFlow = asyncTimeline.data.timelineItems.debounce(300.milliseconds) + val timelineItemsFlow = asyncTimeline.data.timelineItems combine(timelineItemsFlow, room.membersStateFlow) { items, membersState -> timelineItemsFactory.replaceWith( timelineItems = items, From 6b4cce7de342f8e60f0e823254f6ac79abd9e1b8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:14:10 +0200 Subject: [PATCH 09/56] Code cleanup --- .../auth/RustMatrixAuthenticationService.kt | 27 +++++++++---------- .../RustSessionVerificationService.kt | 1 + 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index d1f0d29295..b63e307888 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -251,18 +251,17 @@ class RustMatrixAuthenticationService @Inject constructor( oidcConfiguration = oidcConfiguration, progressListener = progressListener, ) - - client.use { rustClient -> - val sessionData = rustClient.session() + val sessionData = client.use { rustClient -> + rustClient.session() .toSessionData( isTokenValid = true, loginType = LoginType.QR, passphrase = pendingPassphrase, sessionPaths = emptySessionPaths, ) - sessionStore.storeData(sessionData) - SessionId(sessionData.userId) } + sessionStore.storeData(sessionData) + SessionId(sessionData.userId) }.mapFailure { when (it) { is QrCodeDecodeException -> QrErrorMapper.map(it) @@ -285,14 +284,14 @@ class RustMatrixAuthenticationService @Inject constructor( if (slidingSyncType is ClientBuilderSlidingSync.Simplified) { Timber.d("Creating client with simplified sliding sync") try { - return rustMatrixClientFactory - .getBaseClientBuilder( - sessionPaths = sessionPaths, - passphrase = pendingPassphrase, - slidingSyncType = slidingSyncType, - ) - .run { config() } - .build() + return rustMatrixClientFactory + .getBaseClientBuilder( + sessionPaths = sessionPaths, + passphrase = pendingPassphrase, + slidingSyncType = slidingSyncType, + ) + .config() + .build() } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") } @@ -304,7 +303,7 @@ class RustMatrixAuthenticationService @Inject constructor( passphrase = pendingPassphrase, slidingSyncType = getSlidingSyncProxy(), ) - .run { config() } + .config() .build() } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt index 9d55d3402c..71004a74d7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/verification/RustSessionVerificationService.kt @@ -206,6 +206,7 @@ class RustSessionVerificationService( } } } + private suspend fun updateVerificationStatus() { if (verificationFlowState.value == VerificationFlowState.Finished) { // Calling `encryptionService.verificationState()` performs a network call and it will deadlock if there is no network From 7c56bc4c6bb6ff61da5a74b1213deb57234f711c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:14:44 +0200 Subject: [PATCH 10/56] Move FakeRust classes and factories to a fixtures package --- .../matrix/impl/fixtures/FakeRustRoom.kt | 39 ++++++ .../impl/fixtures/FakeRustRoomListItem.kt | 32 +++++ .../fixtures/FakeRustRoomMembersIterator.kt | 31 +++++ .../matrix/impl/fixtures/RustRoomInfo.kt | 81 +++++++++++++ .../matrix/impl/fixtures/RustRoomMember.kt | 34 ++++++ .../room/member/RoomMemberListFetcherTest.kt | 113 ++++-------------- .../roomlist/RoomSummaryListProcessorTest.kt | 103 +--------------- 7 files changed, 244 insertions(+), 189 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt new file mode 100644 index 0000000000..f8f8b88a98 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.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 + +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.Room +import org.matrix.rustcomponents.sdk.RoomMembersIterator + +class FakeRustRoom( + private val getMembers: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, + private val getMembersNoSync: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, +) : Room(NoPointer) { + var membersCallCount = 0 + var membersNoSyncCallCount = 0 + + override fun id(): String { + return A_ROOM_ID.value + } + + override suspend fun members(): RoomMembersIterator { + membersCallCount++ + return getMembers() + } + + override suspend fun membersNoSync(): RoomMembersIterator { + membersNoSyncCallCount++ + return getMembersNoSync() + } + + override fun close() { + // No-op + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt new file mode 100644 index 0000000000..1b9adee435 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt @@ -0,0 +1,32 @@ +/* + * 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 + +import io.element.android.libraries.matrix.api.core.RoomId +import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.RoomListItem + +class FakeRustRoomListItem( + private val roomId: RoomId, + private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), + private val latestEvent: EventTimelineItem? = null, +) : RoomListItem(NoPointer) { + override fun id(): String { + return roomId.value + } + + override suspend fun roomInfo(): RoomInfo { + return roomInfo + } + + override suspend fun latestEvent(): EventTimelineItem? { + return latestEvent + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt new file mode 100644 index 0000000000..e5a0646303 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt @@ -0,0 +1,31 @@ +/* + * 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 + +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.RoomMembersIterator + +class FakeRustRoomMembersIterator( + private var members: List? = null +) : RoomMembersIterator(NoPointer) { + override fun len(): UInt { + return members?.size?.toUInt() ?: 0u + } + + override fun nextChunk(chunkSize: UInt): List? { + if (members?.isEmpty() == true) { + return null + } + return members?.let { + val result = it.take(chunkSize.toInt()) + members = it.subList(result.size, it.size) + result + } + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt new file mode 100644 index 0000000000..e64dabf27a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt @@ -0,0 +1,81 @@ +/* + * 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 + +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_ROOM_NAME +import org.matrix.rustcomponents.sdk.Membership +import org.matrix.rustcomponents.sdk.RoomHero +import org.matrix.rustcomponents.sdk.RoomInfo +import org.matrix.rustcomponents.sdk.RoomMember +import org.matrix.rustcomponents.sdk.RoomNotificationMode + +fun aRustRoomInfo( + id: String = A_ROOM_ID.value, + displayName: String = A_ROOM_NAME, + rawName: String = A_ROOM_NAME, + topic: String? = null, + avatarUrl: String? = null, + isDirect: Boolean = false, + isPublic: Boolean = false, + isSpace: Boolean = false, + isTombstoned: Boolean = false, + isFavourite: Boolean = false, + canonicalAlias: String? = null, + alternativeAliases: List = listOf(), + membership: Membership = Membership.JOINED, + inviter: RoomMember? = null, + heroes: List = listOf(), + activeMembersCount: ULong = 0uL, + invitedMembersCount: ULong = 0uL, + joinedMembersCount: ULong = 0uL, + userPowerLevels: Map = mapOf(), + highlightCount: ULong = 0uL, + notificationCount: ULong = 0uL, + userDefinedNotificationMode: RoomNotificationMode? = null, + hasRoomCall: Boolean = false, + activeRoomCallParticipants: List = listOf(), + isMarkedUnread: Boolean = false, + numUnreadMessages: ULong = 0uL, + numUnreadNotifications: ULong = 0uL, + numUnreadMentions: ULong = 0uL, + pinnedEventIds: List = listOf(), + roomCreator: UserId? = null, +) = RoomInfo( + id = id, + displayName = displayName, + rawName = rawName, + topic = topic, + avatarUrl = avatarUrl, + isDirect = isDirect, + isPublic = isPublic, + isSpace = isSpace, + isTombstoned = isTombstoned, + isFavourite = isFavourite, + canonicalAlias = canonicalAlias, + alternativeAliases = alternativeAliases, + membership = membership, + inviter = inviter, + heroes = heroes, + activeMembersCount = activeMembersCount, + invitedMembersCount = invitedMembersCount, + joinedMembersCount = joinedMembersCount, + userPowerLevels = userPowerLevels, + highlightCount = highlightCount, + notificationCount = notificationCount, + cachedUserDefinedNotificationMode = userDefinedNotificationMode, + hasRoomCall = hasRoomCall, + activeRoomCallParticipants = activeRoomCallParticipants, + isMarkedUnread = isMarkedUnread, + numUnreadMessages = numUnreadMessages, + numUnreadNotifications = numUnreadNotifications, + numUnreadMentions = numUnreadMentions, + pinnedEventIds = pinnedEventIds, + creator = roomCreator?.value, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt new file mode 100644 index 0000000000..918ae1fe12 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt @@ -0,0 +1,34 @@ +/* + * 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 + +import io.element.android.libraries.matrix.api.core.UserId +import org.matrix.rustcomponents.sdk.MembershipState +import org.matrix.rustcomponents.sdk.RoomMember +import uniffi.matrix_sdk.RoomMemberRole + +fun aRustRoomMember( + userId: UserId, + displayName: String? = null, + avatarUrl: String? = null, + membership: MembershipState = MembershipState.JOIN, + isNameAmbiguous: Boolean = false, + powerLevel: Long = 0L, + isIgnored: Boolean = false, + role: RoomMemberRole = RoomMemberRole.USER, +) = RoomMember( + userId = userId.value, + displayName = displayName, + avatarUrl = avatarUrl, + membership = membership, + isNameAmbiguous = isNameAmbiguous, + powerLevel = powerLevel, + normalizedPowerLevel = powerLevel, + isIgnored = isIgnored, + suggestedRoleForPowerLevel = role, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 2411b67c61..87e2f5a0b7 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -9,13 +9,14 @@ package io.element.android.libraries.matrix.impl.room.member import app.cash.turbine.test import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoom +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomMembersIterator +import io.element.android.libraries.matrix.impl.fixtures.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER -import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID_2 import io.element.android.libraries.matrix.test.A_USER_ID_3 @@ -23,22 +24,16 @@ import io.element.android.libraries.matrix.test.A_USER_ID_4 import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.MembershipState -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.Room -import org.matrix.rustcomponents.sdk.RoomMember -import org.matrix.rustcomponents.sdk.RoomMembersIterator -import uniffi.matrix_sdk.RoomMemberRole class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits cached members, if any`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -65,7 +60,7 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits empty list, if no members exist`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator(emptyList()) + FakeRustRoomMembersIterator(emptyList()) }) val fetcher = RoomMemberListFetcher(room, Dispatchers.Default) @@ -95,11 +90,11 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with CACHE source - emits all items at once`() = runTest { val room = FakeRustRoom(getMembersNoSync = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -122,11 +117,11 @@ class RoomMemberListFetcherTest { @Test fun `fetchRoomMembers with SERVER source - emits only new members, if any`() = runTest { val room = FakeRustRoom(getMembers = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) }) @@ -163,14 +158,14 @@ class RoomMemberListFetcherTest { fun `fetchRoomMembers with CACHE_AND_SERVER source - returns cached items first, then new ones`() = runTest { val room = FakeRustRoom( getMembersNoSync = { - FakeRoomMembersIterator(listOf(fakeRustRoomMember(A_USER_ID_4))) + FakeRustRoomMembersIterator(listOf(aRustRoomMember(A_USER_ID_4))) }, getMembers = { - FakeRoomMembersIterator( + FakeRustRoomMembersIterator( listOf( - fakeRustRoomMember(A_USER_ID), - fakeRustRoomMember(A_USER_ID_2), - fakeRustRoomMember(A_USER_ID_3), + aRustRoomMember(A_USER_ID), + aRustRoomMember(A_USER_ID_2), + aRustRoomMember(A_USER_ID_3), ) ) } @@ -203,69 +198,3 @@ class RoomMemberListFetcherTest { } } } - -class FakeRustRoom( - private val getMembers: () -> RoomMembersIterator = { FakeRoomMembersIterator() }, - private val getMembersNoSync: () -> RoomMembersIterator = { FakeRoomMembersIterator() }, -) : Room(NoPointer) { - var membersCallCount = 0 - var membersNoSyncCallCount = 0 - - override fun id(): String { - return A_ROOM_ID.value - } - - override suspend fun members(): RoomMembersIterator { - membersCallCount++ - return getMembers() - } - - override suspend fun membersNoSync(): RoomMembersIterator { - membersNoSyncCallCount++ - return getMembersNoSync() - } - - override fun close() { - // No-op - } -} - -class FakeRoomMembersIterator( - private var members: List? = null -) : RoomMembersIterator(NoPointer) { - override fun len(): UInt { - return members?.size?.toUInt() ?: 0u - } - - override fun nextChunk(chunkSize: UInt): List? { - if (members?.isEmpty() == true) { - return null - } - return members?.let { - val result = it.take(chunkSize.toInt()) - members = it.subList(result.size, it.size) - result - } - } -} - -private fun fakeRustRoomMember( - userId: UserId, - displayName: String? = null, - avatarUrl: String? = null, - membership: MembershipState = MembershipState.JOIN, - isNameAmbiguous: Boolean = false, - powerLevel: Long = 0L, - isIgnored: Boolean = false, - role: RoomMemberRole = RoomMemberRole.USER, -) = RoomMember( - userId = userId.value, - displayName = displayName, - avatarUrl = avatarUrl, - membership = membership, - isNameAmbiguous = isNameAmbiguous, - powerLevel = powerLevel, - normalizedPowerLevel = powerLevel, - isIgnored = isIgnored, - suggestedRoleForPowerLevel = role, -) 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 faa8a1102e..93096ee227 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 @@ -9,12 +9,10 @@ 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.core.RoomId -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.roomlist.RoomSummary +import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem 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_NAME import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import kotlinx.coroutines.flow.MutableStateFlow @@ -22,19 +20,12 @@ import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.EventTimelineItem -import org.matrix.rustcomponents.sdk.Membership -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.RoomHero -import org.matrix.rustcomponents.sdk.RoomInfo 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.RoomMember -import org.matrix.rustcomponents.sdk.RoomNotificationMode import org.matrix.rustcomponents.sdk.RoomSubscription import org.matrix.rustcomponents.sdk.TaskHandle @@ -48,7 +39,7 @@ class RoomSummaryListProcessorTest { summaries.value = listOf(aRoomSummary()) val processor = createProcessor() - val newEntry = FakeRoomListItem(A_ROOM_ID_2) + val newEntry = FakeRustRoomListItem(A_ROOM_ID_2) processor.postUpdate(listOf(RoomListEntriesUpdate.Append(listOf(newEntry, newEntry, newEntry)))) assertThat(summaries.value.count()).isEqualTo(4) @@ -59,7 +50,7 @@ class RoomSummaryListProcessorTest { fun `PushBack adds a new entry at the end of the list`() = runTest { summaries.value = listOf(aRoomSummaryFilled()) val processor = createProcessor() - processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.PushBack(FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2) @@ -69,7 +60,7 @@ class RoomSummaryListProcessorTest { fun `PushFront inserts a new entry at the start of the list`() = runTest { summaries.value = listOf(aRoomSummaryFilled()) val processor = createProcessor() - processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.PushFront(FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2) @@ -81,7 +72,7 @@ class RoomSummaryListProcessorTest { val processor = createProcessor() val index = 0 - processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.Set(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(1) assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) @@ -93,7 +84,7 @@ class RoomSummaryListProcessorTest { val processor = createProcessor() val index = 0 - processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRoomListItem(A_ROOM_ID_2)))) + processor.postUpdate(listOf(RoomListEntriesUpdate.Insert(index.toUInt(), FakeRustRoomListItem(A_ROOM_ID_2)))) assertThat(summaries.value.count()).isEqualTo(2) assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2) @@ -185,85 +176,3 @@ class RoomSummaryListProcessorTest { override fun subscribeToRooms(roomIds: List, settings: RoomSubscription?) = Unit } } - -private fun aRustRoomInfo( - id: String = A_ROOM_ID.value, - displayName: String = A_ROOM_NAME, - rawName: String = A_ROOM_NAME, - topic: String? = null, - avatarUrl: String? = null, - isDirect: Boolean = false, - isPublic: Boolean = false, - isSpace: Boolean = false, - isTombstoned: Boolean = false, - isFavourite: Boolean = false, - canonicalAlias: String? = null, - alternativeAliases: List = listOf(), - membership: Membership = Membership.JOINED, - inviter: RoomMember? = null, - heroes: List = listOf(), - activeMembersCount: ULong = 0uL, - invitedMembersCount: ULong = 0uL, - joinedMembersCount: ULong = 0uL, - userPowerLevels: Map = mapOf(), - highlightCount: ULong = 0uL, - notificationCount: ULong = 0uL, - userDefinedNotificationMode: RoomNotificationMode? = null, - hasRoomCall: Boolean = false, - activeRoomCallParticipants: List = listOf(), - isMarkedUnread: Boolean = false, - numUnreadMessages: ULong = 0uL, - numUnreadNotifications: ULong = 0uL, - numUnreadMentions: ULong = 0uL, - pinnedEventIds: List = listOf(), - roomCreator: UserId? = null, -) = RoomInfo( - id = id, - displayName = displayName, - rawName = rawName, - topic = topic, - avatarUrl = avatarUrl, - isDirect = isDirect, - isPublic = isPublic, - isSpace = isSpace, - isTombstoned = isTombstoned, - isFavourite = isFavourite, - canonicalAlias = canonicalAlias, - alternativeAliases = alternativeAliases, - membership = membership, - inviter = inviter, - heroes = heroes, - activeMembersCount = activeMembersCount, - invitedMembersCount = invitedMembersCount, - joinedMembersCount = joinedMembersCount, - userPowerLevels = userPowerLevels, - highlightCount = highlightCount, - notificationCount = notificationCount, - cachedUserDefinedNotificationMode = userDefinedNotificationMode, - hasRoomCall = hasRoomCall, - activeRoomCallParticipants = activeRoomCallParticipants, - isMarkedUnread = isMarkedUnread, - numUnreadMessages = numUnreadMessages, - numUnreadNotifications = numUnreadNotifications, - numUnreadMentions = numUnreadMentions, - pinnedEventIds = pinnedEventIds, - creator = roomCreator?.value, -) - -class FakeRoomListItem( - private val roomId: RoomId, - private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value), - private val latestEvent: EventTimelineItem? = null, -) : RoomListItem(NoPointer) { - override fun id(): String { - return roomId.value - } - - override suspend fun roomInfo(): RoomInfo { - return roomInfo - } - - override suspend fun latestEvent(): EventTimelineItem? { - return latestEvent - } -} From 352dbdb9cbb63950aa824b1f77bd130e7d79adce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 14:26:45 +0200 Subject: [PATCH 11/56] Cleanup tests. --- .../libraries/matrix/impl/fixtures/FakeRustRoom.kt | 14 ++++++-------- .../impl/room/member/RoomMemberListFetcherTest.kt | 12 ------------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt index f8f8b88a98..a9321bf347 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt @@ -7,29 +7,27 @@ package io.element.android.libraries.matrix.impl.fixtures +import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.lambda.lambdaError import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.Room import org.matrix.rustcomponents.sdk.RoomMembersIterator class FakeRustRoom( - private val getMembers: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, - private val getMembersNoSync: () -> RoomMembersIterator = { FakeRustRoomMembersIterator() }, + private val roomId: RoomId = A_ROOM_ID, + private val getMembers: () -> RoomMembersIterator = { lambdaError() }, + private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() }, ) : Room(NoPointer) { - var membersCallCount = 0 - var membersNoSyncCallCount = 0 - override fun id(): String { - return A_ROOM_ID.value + return roomId.value } override suspend fun members(): RoomMembersIterator { - membersCallCount++ return getMembers() } override suspend fun membersNoSync(): RoomMembersIterator { - membersNoSyncCallCount++ return getMembersNoSync() } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 87e2f5a0b7..dc8489e48f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -50,10 +50,6 @@ class RoomMemberListFetcherTest { val cachedItemsState = awaitItem() assertThat(cachedItemsState).isInstanceOf(MatrixRoomMembersState.Ready::class.java) assertThat((cachedItemsState as? MatrixRoomMembersState.Ready)?.roomMembers).hasSize(3) - - // Assert only the 'no sync' method was called, so no new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(1) - assertThat(room.membersCallCount).isEqualTo(0) } } @@ -133,10 +129,6 @@ class RoomMemberListFetcherTest { assertThat(awaitItem()).isInstanceOf(MatrixRoomMembersState.Unknown::class.java) assertThat(awaitItem()).isInstanceOf(MatrixRoomMembersState.Pending::class.java) assertThat((awaitItem() as? MatrixRoomMembersState.Ready)?.roomMembers?.size).isEqualTo(3) - - // Assert only the 'sync' method was called, so a new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(0) - assertThat(room.membersCallCount).isEqualTo(1) } } @@ -191,10 +183,6 @@ class RoomMemberListFetcherTest { assertThat(ready).isInstanceOf(MatrixRoomMembersState.Ready::class.java) assertThat(ready.roomMembers()).hasSize(3) } - - // Assert both member methods were called, so both the cache was hit and a new member sync happened - assertThat(room.membersNoSyncCallCount).isEqualTo(1) - assertThat(room.membersCallCount).isEqualTo(1) } } } From 1242316c05de68c78e42b18e943a9f40469c6aaf Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 14:01:24 +0200 Subject: [PATCH 12/56] Timeline : makes sure we don't emit empty list when navigating back to timeline. --- .../features/messages/impl/timeline/TimelinePresenter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt index 088354f245..29a2786bc0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelinePresenter.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -81,6 +82,7 @@ class TimelinePresenter @AssistedInject constructor( computeReactions = true, ) ) + private var timelineItems by mutableStateOf>(persistentListOf()) @Composable override fun present(): TimelineState { @@ -89,9 +91,12 @@ class TimelinePresenter @AssistedInject constructor( mutableStateOf(FocusRequestState.None) } + LaunchedEffect(Unit) { + timelineItemsFactory.timelineItems.collect { timelineItems = it } + } + val lastReadReceiptId = rememberSaveable { mutableStateOf(null) } - val timelineItems by timelineItemsFactory.timelineItems.collectAsState(initial = persistentListOf()) val roomInfo by room.roomInfoFlow.collectAsState(initial = null) val syncUpdateFlow = room.syncUpdateFlow.collectAsState() From d5ac6dabdf303c78ac346a4ed3917d4403a3a81c Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Wed, 18 Sep 2024 17:02:49 +0200 Subject: [PATCH 13/56] Fix sliding sync proxy login not working after native SS failure (#3489) --- .../matrix/impl/auth/RustMatrixAuthenticationService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt index b63e307888..47a81e9f65 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext import org.matrix.rustcomponents.sdk.Client +import org.matrix.rustcomponents.sdk.ClientBuildException import org.matrix.rustcomponents.sdk.ClientBuilder import org.matrix.rustcomponents.sdk.HumanQrLoginException import org.matrix.rustcomponents.sdk.OidcConfiguration @@ -292,7 +293,7 @@ class RustMatrixAuthenticationService @Inject constructor( ) .config() .build() - } catch (e: HumanQrLoginException.SlidingSyncNotAvailable) { + } catch (e: ClientBuildException.SlidingSyncVersion) { Timber.e(e, "Failed to create client with simplified sliding sync, trying with Proxy now") } } From 30847e9e1f95e215a520f0448c256c6158a5d90a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:09:02 +0200 Subject: [PATCH 14/56] Add unit test on toAnalyticsJoinedRoom and fix a mapping issue. --- .../matrix/impl/analytics/JoinedRoomExt.kt | 5 +- .../impl/analytics/JoinedRoomExtKtTest.kt | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt index a454c1b58f..81ef1672e3 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExt.kt @@ -10,9 +10,10 @@ package io.element.android.libraries.matrix.impl.analytics import im.vector.app.features.analytics.plan.JoinedRoom import io.element.android.libraries.matrix.api.room.MatrixRoom -private fun Long?.toAnalyticsRoomSize(): JoinedRoom.RoomSize { +private fun Long.toAnalyticsRoomSize(): JoinedRoom.RoomSize { return when (this) { - null, + 0L, + 1L -> JoinedRoom.RoomSize.One 2L -> JoinedRoom.RoomSize.Two in 3..10 -> JoinedRoom.RoomSize.ThreeToTen in 11..100 -> JoinedRoom.RoomSize.ElevenToOneHundred diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt new file mode 100644 index 0000000000..6140f32b2e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/analytics/JoinedRoomExtKtTest.kt @@ -0,0 +1,91 @@ +/* + * 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.analytics + +import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.test.room.FakeMatrixRoom +import org.junit.Test + +class JoinedRoomExtKtTest { + @Test + fun `test room size mapping`() { + mapOf( + listOf(0L, 1L) to JoinedRoom.RoomSize.One, + listOf(2L, 2L) to JoinedRoom.RoomSize.Two, + listOf(3L, 10L) to JoinedRoom.RoomSize.ThreeToTen, + listOf(11L, 100L) to JoinedRoom.RoomSize.ElevenToOneHundred, + listOf(101L, 1000L) to JoinedRoom.RoomSize.OneHundredAndOneToAThousand, + listOf(1001L, 2000L) to JoinedRoom.RoomSize.MoreThanAThousand + ).forEach { (joinedMemberCounts, expectedRoomSize) -> + joinedMemberCounts.forEach { joinedMemberCount -> + assertThat(aMatrixRoom(joinedMemberCount = joinedMemberCount).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = expectedRoomSize, + trigger = null + ) + ) + } + } + } + + @Test + fun `test isDirect parameter mapping`() { + assertThat(aMatrixRoom(isDirect = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = true, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test isSpace parameter mapping`() { + assertThat(aMatrixRoom(isSpace = true).toAnalyticsJoinedRoom(null)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = true, + roomSize = JoinedRoom.RoomSize.One, + trigger = null + ) + ) + } + + @Test + fun `test trigger parameter mapping`() { + assertThat(aMatrixRoom().toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + .isEqualTo( + JoinedRoom( + isDM = false, + isSpace = false, + roomSize = JoinedRoom.RoomSize.One, + trigger = JoinedRoom.Trigger.Invite + ) + ) + } + + private fun aMatrixRoom( + isDirect: Boolean = false, + isSpace: Boolean = false, + joinedMemberCount: Long = 0 + ): MatrixRoom { + return FakeMatrixRoom( + isDirect = isDirect, + isSpace = isSpace, + joinedMemberCount = joinedMemberCount + ) + } +} From e43491ac5a6324f2195f4e532855704d018b74c5 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:19:38 +0200 Subject: [PATCH 15/56] Add unit test on QrErrorMapper --- .../impl/auth/qrlogin/QrErrorMapperTest.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.kt new file mode 100644 index 0000000000..3bbb98fb34 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrErrorMapperTest.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.qrlogin + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeDecodeException +import io.element.android.libraries.matrix.api.auth.qrlogin.QrLoginException +import org.junit.Test +import org.matrix.rustcomponents.sdk.HumanQrLoginException as RustHumanQrLoginException +import org.matrix.rustcomponents.sdk.QrCodeDecodeException as RustQrCodeDecodeException + +class QrErrorMapperTest { + @Test + fun `test map QrCodeDecodeException`() { + val result = QrErrorMapper.map(RustQrCodeDecodeException.Crypto("test")) + assertThat(result).isInstanceOf(QrCodeDecodeException.Crypto::class.java) + assertThat(result.message).isEqualTo("test") + } + + @Test + fun `test map HumanQrLoginException`() { + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Cancelled())).isEqualTo(QrLoginException.Cancelled) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.ConnectionInsecure())).isEqualTo(QrLoginException.ConnectionInsecure) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Declined())).isEqualTo(QrLoginException.Declined) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Expired())).isEqualTo(QrLoginException.Expired) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OtherDeviceNotSignedIn())).isEqualTo(QrLoginException.OtherDeviceNotSignedIn) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.LinkingNotSupported())).isEqualTo(QrLoginException.LinkingNotSupported) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.Unknown())).isEqualTo(QrLoginException.Unknown) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.OidcMetadataInvalid())).isEqualTo(QrLoginException.OidcMetadataInvalid) + assertThat(QrErrorMapper.map(RustHumanQrLoginException.SlidingSyncNotAvailable())).isEqualTo(QrLoginException.SlidingSyncNotAvailable) + } +} From 18461fa1f175ab2423562c7db4d8a23b4f3d7820 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:24:42 +0200 Subject: [PATCH 16/56] Add unit test on QrLoginProgress.toStep() --- .../QrLoginProgressExtensionsKtTest.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt new file mode 100644 index 0000000000..0de3d15e57 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt @@ -0,0 +1,29 @@ +/* + * 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.qrlogin + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep +import org.junit.Test +import org.matrix.rustcomponents.sdk.QrLoginProgress + +class QrLoginProgressExtensionsKtTest { + @Test + fun `mapping QrLoginProgress should return expected result`() { + assertThat(QrLoginProgress.Starting.toStep()) + .isEqualTo(QrCodeLoginStep.Starting) + assertThat(QrLoginProgress.EstablishingSecureChannel(1u, "01").toStep()) + .isEqualTo(QrCodeLoginStep.EstablishingSecureChannel("01")) + assertThat(QrLoginProgress.WaitingForToken("userCode").toStep()) + .isEqualTo(QrCodeLoginStep.WaitingForToken("userCode")) + assertThat(QrLoginProgress.Done.toStep()) + .isEqualTo(QrCodeLoginStep.Finished) + } +} + + From 25fd71cb2c3517768a33ccde4d4ba6d7e10db1b4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:40:26 +0200 Subject: [PATCH 17/56] Make sure Throwable.mapAuthenticationException() is exhaustive on mapping ClientBuildException and add test for full coverage. --- .../matrix/impl/auth/AuthenticationException.kt | 15 +++++++++++---- .../auth/AuthenticationExceptionMappingTest.kt | 17 ++++++++++++++--- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt index 278b814fe2..cf48d68c70 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationException.kt @@ -8,14 +8,21 @@ package io.element.android.libraries.matrix.impl.auth import io.element.android.libraries.matrix.api.auth.AuthenticationException -import org.matrix.rustcomponents.sdk.ClientBuildException as RustAuthenticationException +import org.matrix.rustcomponents.sdk.ClientBuildException fun Throwable.mapAuthenticationException(): AuthenticationException { val message = this.message ?: "Unknown error" return when (this) { - is RustAuthenticationException.Generic -> AuthenticationException.Generic(message) - is RustAuthenticationException.InvalidServerName -> AuthenticationException.InvalidServerName(message) - is RustAuthenticationException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message) + is ClientBuildException -> when (this) { + is ClientBuildException.Generic -> AuthenticationException.Generic(message) + is ClientBuildException.InvalidServerName -> AuthenticationException.InvalidServerName(message) + is ClientBuildException.SlidingSyncVersion -> AuthenticationException.SlidingSyncVersion(message) + is ClientBuildException.Sdk -> AuthenticationException.Generic(message) + is ClientBuildException.ServerUnreachable -> AuthenticationException.Generic(message) + is ClientBuildException.SlidingSync -> AuthenticationException.Generic(message) + is ClientBuildException.WellKnownDeserializationException -> AuthenticationException.Generic(message) + is ClientBuildException.WellKnownLookupFailed -> AuthenticationException.Generic(message) + } else -> AuthenticationException.Generic(message) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt index fd007151c8..81a1667f4e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/AuthenticationExceptionMappingTest.kt @@ -36,13 +36,24 @@ class AuthenticationExceptionMappingTest { assertThat(ClientBuildException.InvalidServerName("Invalid server name").mapAuthenticationException()) .isException("Invalid server name") - assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException()) - .isException("SDK issue") - assertThat(ClientBuildException.SlidingSyncVersion("Sliding sync not available").mapAuthenticationException()) .isException("Sliding sync not available") } + @Test + fun `mapping other exceptions map to the Generic Kotlin`() { + assertThat(ClientBuildException.Sdk("SDK issue").mapAuthenticationException()) + .isException("SDK issue") + assertThat(ClientBuildException.ServerUnreachable("Server unreachable").mapAuthenticationException()) + .isException("Server unreachable") + assertThat(ClientBuildException.SlidingSync("Sliding Sync").mapAuthenticationException()) + .isException("Sliding Sync") + assertThat(ClientBuildException.WellKnownDeserializationException("WellKnown Deserialization").mapAuthenticationException()) + .isException("WellKnown Deserialization") + assertThat(ClientBuildException.WellKnownLookupFailed("WellKnown Lookup Failed").mapAuthenticationException()) + .isException("WellKnown Lookup Failed") + } + private inline fun ThrowableSubject.isException(message: String) { isInstanceOf(T::class.java) hasMessageThat().isEqualTo(message) From 021d7297e57a809a426598730da45267b10502da Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:47:55 +0200 Subject: [PATCH 18/56] Add unit test on ProgressWatcherWrapper --- .../impl/core/ProgressWatcherWrapperKtTest.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt new file mode 100644 index 0000000000..316c69ebb7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/core/ProgressWatcherWrapperKtTest.kt @@ -0,0 +1,33 @@ +/* + * 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.core + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.ProgressCallback +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.TransmissionProgress +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +class ProgressWatcherWrapperKtTest { + @Test + fun testToProgressWatcher() = runTest { + suspendCoroutine { continuation -> + val callback = object : ProgressCallback { + override fun onProgress(current: Long, total: Long) { + assertThat(current).isEqualTo(1) + assertThat(total).isEqualTo(2) + continuation.resume(Unit) + } + } + val result = callback.toProgressWatcher() + result.transmissionProgress(TransmissionProgress(1.toULong(), 2.toULong())) + } + } +} From eca112fcc0c4c161ee1d175778eea8b71e194a43 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:52:46 +0200 Subject: [PATCH 19/56] Add unit test on providesTracingFilterConfiguration --- .../matrix/impl/di/TracingMatrixModuleTest.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt new file mode 100644 index 0000000000..687ca3d56c --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/di/TracingMatrixModuleTest.kt @@ -0,0 +1,34 @@ +/* + * 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.di + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations +import io.element.android.libraries.matrix.test.core.aBuildMeta +import org.junit.Test + +class TracingMatrixModuleTest { + @Test + fun `providesTracingFilterConfiguration returns debug config for debug build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.DEBUG))) + .isEqualTo(TracingFilterConfigurations.debug) + } + + @Test + fun `providesTracingFilterConfiguration returns nightly config for nightly build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.NIGHTLY))) + .isEqualTo(TracingFilterConfigurations.nightly) + } + + @Test + fun `providesTracingFilterConfiguration returns release config for release build`() { + assertThat(TracingMatrixModule.providesTracingFilterConfiguration(aBuildMeta(BuildType.RELEASE))) + .isEqualTo(TracingFilterConfigurations.release) + } +} From 5b8e99149a7c283c0d7b1ec79e70a83f5494c71a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 12:58:00 +0200 Subject: [PATCH 20/56] Add unit test on crypto mappers --- .../impl/encryption/BackupStateMapperTest.kt | 26 +++++++++++++++ .../encryption/BackupUploadStateMapperTest.kt | 33 +++++++++++++++++++ .../EnableRecoveryProgressMapperTest.kt | 31 +++++++++++++++++ .../encryption/RecoveryStateMapperTest.kt | 23 +++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt new file mode 100644 index 0000000000..fc804b0978 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt @@ -0,0 +1,26 @@ +/* + * 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.encryption + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.encryption.BackupState +import org.junit.Test +import org.matrix.rustcomponents.sdk.BackupState as RustBackupState + +class BackupStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(BackupStateMapper().map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) + assertThat(BackupStateMapper().map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) + assertThat(BackupStateMapper().map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) + assertThat(BackupStateMapper().map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) + assertThat(BackupStateMapper().map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) + assertThat(BackupStateMapper().map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) + assertThat(BackupStateMapper().map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt new file mode 100644 index 0000000000..7c1ad1d7c5 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt @@ -0,0 +1,33 @@ +/* + * 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.encryption + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.encryption.BackupUploadState +import org.junit.Test +import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState + +class BackupUploadStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Waiting)) + .isEqualTo(BackupUploadState.Waiting) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Error)) + .isEqualTo(BackupUploadState.Error) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Done)) + .isEqualTo(BackupUploadState.Done) + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) + .isEqualTo(BackupUploadState.Uploading(1, 2)) + } + + @Test + fun `Ensure that full uploading is mapper to Done`() { + assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) + .isEqualTo(BackupUploadState.Done) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt new file mode 100644 index 0000000000..191a7f3964 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt @@ -0,0 +1,31 @@ +/* + * 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.encryption + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.encryption.EnableRecoveryProgress +import org.junit.Test +import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecoveryProgress + +class EnableRecoveryProgressMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingRecoveryKey)) + .isEqualTo(EnableRecoveryProgress.CreatingRecoveryKey) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingBackup)) + .isEqualTo(EnableRecoveryProgress.CreatingBackup) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Starting)) + .isEqualTo(EnableRecoveryProgress.Starting) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) + .isEqualTo(EnableRecoveryProgress.BackingUp(1, 2)) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.RoomKeyUploadError)) + .isEqualTo(EnableRecoveryProgress.RoomKeyUploadError) + assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Done("recoveryKey"))) + .isEqualTo(EnableRecoveryProgress.Done("recoveryKey")) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt new file mode 100644 index 0000000000..9d7c2d0c04 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.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.encryption + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.encryption.RecoveryState +import org.junit.Test +import org.matrix.rustcomponents.sdk.RecoveryState as RustRecoveryState + +class RecoveryStateMapperTest { + @Test + fun `Ensure that mapping is correct`() { + assertThat(RecoveryStateMapper().map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) + assertThat(RecoveryStateMapper().map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) + assertThat(RecoveryStateMapper().map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) + assertThat(RecoveryStateMapper().map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) + } +} From 5b44eab444b25934cab23ca5495b2316ca1be28a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:05:45 +0200 Subject: [PATCH 21/56] Ensure mapping of Rust exceptions cover all cases. --- .../impl/encryption/RecoveryExceptionMapper.kt | 18 +++++++++++------- .../matrix/impl/exception/ClientException.kt | 6 +++++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt index e200ca5434..b33d59375b 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryExceptionMapper.kt @@ -14,13 +14,17 @@ import org.matrix.rustcomponents.sdk.RecoveryException as RustRecoveryException fun Throwable.mapRecoveryException(): RecoveryException { return when (this) { - is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage( - message = errorMessage - ) - is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer - is RustRecoveryException.Client -> RecoveryException.Client( - source.mapClientException() - ) + is RustRecoveryException -> { + when (this) { + is RustRecoveryException.SecretStorage -> RecoveryException.SecretStorage( + message = errorMessage + ) + is RustRecoveryException.BackupExistsOnServer -> RecoveryException.BackupExistsOnServer + is RustRecoveryException.Client -> RecoveryException.Client( + source.mapClientException() + ) + } + } else -> RecoveryException.Client( ClientException.Other("Unknown error") ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt index c15b873d73..87364930ce 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/exception/ClientException.kt @@ -12,7 +12,11 @@ import org.matrix.rustcomponents.sdk.ClientException as RustClientException fun Throwable.mapClientException(): ClientException { return when (this) { - is RustClientException.Generic -> ClientException.Generic(msg) + is RustClientException -> { + when (this) { + is RustClientException.Generic -> ClientException.Generic(msg) + } + } else -> ClientException.Other(message ?: "Unknown error") } } From 03b9a0f3137d63c5a40f49ba2e6935bb72309c37 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:26:29 +0200 Subject: [PATCH 22/56] Add unit test on mappers --- .../matrix/impl/room/StateEventTypeTest.kt | 68 +++++++++++++++++++ .../powerlevels/RoomPowerLevelsMapperTest.kt | 46 +++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt new file mode 100644 index 0000000000..3772ae780d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt @@ -0,0 +1,68 @@ +/* + * 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.google.common.truth.Truth.assertThat +import org.junit.Test + +import io.element.android.libraries.matrix.api.room.StateEventType +import org.matrix.rustcomponents.sdk.StateEventType as RustStateEventType + +class StateEventTypeTest { + @Test + fun `mapping Rust type should work`() { + assertThat(RustStateEventType.CALL_MEMBER.map()).isEqualTo(StateEventType.CALL_MEMBER) + assertThat(RustStateEventType.POLICY_RULE_ROOM.map()).isEqualTo(StateEventType.POLICY_RULE_ROOM) + assertThat(RustStateEventType.POLICY_RULE_SERVER.map()).isEqualTo(StateEventType.POLICY_RULE_SERVER) + assertThat(RustStateEventType.POLICY_RULE_USER.map()).isEqualTo(StateEventType.POLICY_RULE_USER) + assertThat(RustStateEventType.ROOM_ALIASES.map()).isEqualTo(StateEventType.ROOM_ALIASES) + assertThat(RustStateEventType.ROOM_AVATAR.map()).isEqualTo(StateEventType.ROOM_AVATAR) + assertThat(RustStateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(StateEventType.ROOM_CANONICAL_ALIAS) + assertThat(RustStateEventType.ROOM_CREATE.map()).isEqualTo(StateEventType.ROOM_CREATE) + assertThat(RustStateEventType.ROOM_ENCRYPTION.map()).isEqualTo(StateEventType.ROOM_ENCRYPTION) + assertThat(RustStateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(StateEventType.ROOM_GUEST_ACCESS) + assertThat(RustStateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(StateEventType.ROOM_HISTORY_VISIBILITY) + assertThat(RustStateEventType.ROOM_JOIN_RULES.map()).isEqualTo(StateEventType.ROOM_JOIN_RULES) + assertThat(RustStateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(StateEventType.ROOM_MEMBER_EVENT) + assertThat(RustStateEventType.ROOM_NAME.map()).isEqualTo(StateEventType.ROOM_NAME) + assertThat(RustStateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(StateEventType.ROOM_PINNED_EVENTS) + assertThat(RustStateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(StateEventType.ROOM_POWER_LEVELS) + assertThat(RustStateEventType.ROOM_SERVER_ACL.map()).isEqualTo(StateEventType.ROOM_SERVER_ACL) + assertThat(RustStateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(StateEventType.ROOM_THIRD_PARTY_INVITE) + assertThat(RustStateEventType.ROOM_TOMBSTONE.map()).isEqualTo(StateEventType.ROOM_TOMBSTONE) + assertThat(RustStateEventType.ROOM_TOPIC.map()).isEqualTo(StateEventType.ROOM_TOPIC) + assertThat(RustStateEventType.SPACE_CHILD.map()).isEqualTo(StateEventType.SPACE_CHILD) + assertThat(RustStateEventType.SPACE_PARENT.map()).isEqualTo(StateEventType.SPACE_PARENT) + } + + @Test + fun `mapping Kotlin type should work`() { + assertThat(StateEventType.CALL_MEMBER.map()).isEqualTo(RustStateEventType.CALL_MEMBER) + assertThat(StateEventType.POLICY_RULE_ROOM.map()).isEqualTo(RustStateEventType.POLICY_RULE_ROOM) + assertThat(StateEventType.POLICY_RULE_SERVER.map()).isEqualTo(RustStateEventType.POLICY_RULE_SERVER) + assertThat(StateEventType.POLICY_RULE_USER.map()).isEqualTo(RustStateEventType.POLICY_RULE_USER) + assertThat(StateEventType.ROOM_ALIASES.map()).isEqualTo(RustStateEventType.ROOM_ALIASES) + assertThat(StateEventType.ROOM_AVATAR.map()).isEqualTo(RustStateEventType.ROOM_AVATAR) + assertThat(StateEventType.ROOM_CANONICAL_ALIAS.map()).isEqualTo(RustStateEventType.ROOM_CANONICAL_ALIAS) + assertThat(StateEventType.ROOM_CREATE.map()).isEqualTo(RustStateEventType.ROOM_CREATE) + assertThat(StateEventType.ROOM_ENCRYPTION.map()).isEqualTo(RustStateEventType.ROOM_ENCRYPTION) + assertThat(StateEventType.ROOM_GUEST_ACCESS.map()).isEqualTo(RustStateEventType.ROOM_GUEST_ACCESS) + assertThat(StateEventType.ROOM_HISTORY_VISIBILITY.map()).isEqualTo(RustStateEventType.ROOM_HISTORY_VISIBILITY) + assertThat(StateEventType.ROOM_JOIN_RULES.map()).isEqualTo(RustStateEventType.ROOM_JOIN_RULES) + assertThat(StateEventType.ROOM_MEMBER_EVENT.map()).isEqualTo(RustStateEventType.ROOM_MEMBER_EVENT) + assertThat(StateEventType.ROOM_NAME.map()).isEqualTo(RustStateEventType.ROOM_NAME) + assertThat(StateEventType.ROOM_PINNED_EVENTS.map()).isEqualTo(RustStateEventType.ROOM_PINNED_EVENTS) + assertThat(StateEventType.ROOM_POWER_LEVELS.map()).isEqualTo(RustStateEventType.ROOM_POWER_LEVELS) + assertThat(StateEventType.ROOM_SERVER_ACL.map()).isEqualTo(RustStateEventType.ROOM_SERVER_ACL) + assertThat(StateEventType.ROOM_THIRD_PARTY_INVITE.map()).isEqualTo(RustStateEventType.ROOM_THIRD_PARTY_INVITE) + assertThat(StateEventType.ROOM_TOMBSTONE.map()).isEqualTo(RustStateEventType.ROOM_TOMBSTONE) + assertThat(StateEventType.ROOM_TOPIC.map()).isEqualTo(RustStateEventType.ROOM_TOPIC) + assertThat(StateEventType.SPACE_CHILD.map()).isEqualTo(RustStateEventType.SPACE_CHILD) + assertThat(StateEventType.SPACE_PARENT.map()).isEqualTo(RustStateEventType.SPACE_PARENT) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt new file mode 100644 index 0000000000..2a8a89004d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt @@ -0,0 +1,46 @@ +/* + * 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.powerlevels + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomPowerLevels as RustRoomPowerLevels + +class RoomPowerLevelsMapperTest { + @Test + fun `test that mapping of RoomPowerLevels is correct`() { + assertThat( + RoomPowerLevelsMapper.map( + RustRoomPowerLevels( + ban = 1, + invite = 2, + kick = 3, + redact = 4, + eventsDefault = 5, + stateDefault = 6, + usersDefault = 7, + roomName = 8, + roomAvatar = 9, + roomTopic = 10, + ) + ) + ).isEqualTo( + MatrixRoomPowerLevels( + ban = 1, + invite = 2, + kick = 3, + sendEvents = 5, + redactEvents = 4, + roomName = 8, + roomAvatar = 9, + roomTopic = 10, + ) + ) + } +} From 764b0cf8d3194c4d0b1810f605e2374477fcaa70 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:39:17 +0200 Subject: [PATCH 23/56] Add unit test on elementHeroes() --- .../matrix/impl/room/RoomInfoExtTest.kt | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt new file mode 100644 index 0000000000..7c5c873155 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -0,0 +1,76 @@ +/* + * 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.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.fixtures.aRustRoomInfo +import io.element.android.libraries.matrix.test.A_USER_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomHero + +class RoomInfoExtTest { + @Test + fun `get non empty element Heroes`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEqualTo( + listOf( + MatrixUser( + userId = UserId(A_USER_ID.value), + displayName = "displayName", + avatarUrl = "avatarUrl", + ) + ) + ) + } + + @Test + fun `too many heroes and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero(), aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } + + @Test + fun `not direct and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = false, + activeMembersCount = 2uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } + + @Test + fun `too many members and element Heroes is empty`() { + val result = aRustRoomInfo( + isDirect = true, + activeMembersCount = 3uL, + heroes = listOf(aRoomHero()) + ).elementHeroes() + assertThat(result).isEmpty() + } +} + +private fun aRoomHero( + userId: UserId = A_USER_ID, +): RoomHero { + return RoomHero( + userId = userId.value, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) +} From 56ac755b62e0bc9aa0403a7bd6f83a75c5721e5a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:42:23 +0200 Subject: [PATCH 24/56] Add unit test on MessageEventType mappers --- .../impl/room/MessageEventTypeKtTest.kt | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt new file mode 100644 index 0000000000..847c41e89a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt @@ -0,0 +1,70 @@ +/* + * 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.google.common.truth.Truth.assertThat +import org.junit.Test + +import io.element.android.libraries.matrix.api.room.MessageEventType +import org.matrix.rustcomponents.sdk.MessageLikeEventType + +class MessageEventTypeKtTest { + @Test + fun `map Rust type should result to correct Kotlin type`() { + assertThat(MessageLikeEventType.CALL_ANSWER.map()).isEqualTo(MessageEventType.CALL_ANSWER) + assertThat(MessageLikeEventType.CALL_INVITE.map()).isEqualTo(MessageEventType.CALL_INVITE) + assertThat(MessageLikeEventType.CALL_HANGUP.map()).isEqualTo(MessageEventType.CALL_HANGUP) + assertThat(MessageLikeEventType.CALL_CANDIDATES.map()).isEqualTo(MessageEventType.CALL_CANDIDATES) + assertThat(MessageLikeEventType.CALL_NOTIFY.map()).isEqualTo(MessageEventType.CALL_NOTIFY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_READY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_START) + assertThat(MessageLikeEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_CANCEL) + assertThat(MessageLikeEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_ACCEPT) + assertThat(MessageLikeEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_KEY) + assertThat(MessageLikeEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_MAC) + assertThat(MessageLikeEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageEventType.KEY_VERIFICATION_DONE) + assertThat(MessageLikeEventType.REACTION.map()).isEqualTo(MessageEventType.REACTION) + assertThat(MessageLikeEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageEventType.ROOM_ENCRYPTED) + assertThat(MessageLikeEventType.ROOM_MESSAGE.map()).isEqualTo(MessageEventType.ROOM_MESSAGE) + assertThat(MessageLikeEventType.ROOM_REDACTION.map()).isEqualTo(MessageEventType.ROOM_REDACTION) + assertThat(MessageLikeEventType.STICKER.map()).isEqualTo(MessageEventType.STICKER) + assertThat(MessageLikeEventType.POLL_END.map()).isEqualTo(MessageEventType.POLL_END) + assertThat(MessageLikeEventType.POLL_RESPONSE.map()).isEqualTo(MessageEventType.POLL_RESPONSE) + assertThat(MessageLikeEventType.POLL_START.map()).isEqualTo(MessageEventType.POLL_START) + assertThat(MessageLikeEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_END) + assertThat(MessageLikeEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_RESPONSE) + assertThat(MessageLikeEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageEventType.UNSTABLE_POLL_START) + } + + @Test + fun `map Kotlin type should result to correct Rust type`() { + assertThat(MessageEventType.CALL_ANSWER.map()).isEqualTo(MessageLikeEventType.CALL_ANSWER) + assertThat(MessageEventType.CALL_INVITE.map()).isEqualTo(MessageLikeEventType.CALL_INVITE) + assertThat(MessageEventType.CALL_HANGUP.map()).isEqualTo(MessageLikeEventType.CALL_HANGUP) + assertThat(MessageEventType.CALL_CANDIDATES.map()).isEqualTo(MessageLikeEventType.CALL_CANDIDATES) + assertThat(MessageEventType.CALL_NOTIFY.map()).isEqualTo(MessageLikeEventType.CALL_NOTIFY) + assertThat(MessageEventType.KEY_VERIFICATION_READY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_READY) + assertThat(MessageEventType.KEY_VERIFICATION_START.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_START) + assertThat(MessageEventType.KEY_VERIFICATION_CANCEL.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_CANCEL) + assertThat(MessageEventType.KEY_VERIFICATION_ACCEPT.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_ACCEPT) + assertThat(MessageEventType.KEY_VERIFICATION_KEY.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_KEY) + assertThat(MessageEventType.KEY_VERIFICATION_MAC.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_MAC) + assertThat(MessageEventType.KEY_VERIFICATION_DONE.map()).isEqualTo(MessageLikeEventType.KEY_VERIFICATION_DONE) + assertThat(MessageEventType.REACTION.map()).isEqualTo(MessageLikeEventType.REACTION) + assertThat(MessageEventType.ROOM_ENCRYPTED.map()).isEqualTo(MessageLikeEventType.ROOM_ENCRYPTED) + assertThat(MessageEventType.ROOM_MESSAGE.map()).isEqualTo(MessageLikeEventType.ROOM_MESSAGE) + assertThat(MessageEventType.ROOM_REDACTION.map()).isEqualTo(MessageLikeEventType.ROOM_REDACTION) + assertThat(MessageEventType.STICKER.map()).isEqualTo(MessageLikeEventType.STICKER) + assertThat(MessageEventType.POLL_END.map()).isEqualTo(MessageLikeEventType.POLL_END) + assertThat(MessageEventType.POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.POLL_RESPONSE) + assertThat(MessageEventType.POLL_START.map()).isEqualTo(MessageLikeEventType.POLL_START) + assertThat(MessageEventType.UNSTABLE_POLL_END.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_END) + assertThat(MessageEventType.UNSTABLE_POLL_RESPONSE.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_RESPONSE) + assertThat(MessageEventType.UNSTABLE_POLL_START.map()).isEqualTo(MessageLikeEventType.UNSTABLE_POLL_START) + } +} From 79032235859b9af84e73b38c12071ca8c7970743 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:54:40 +0200 Subject: [PATCH 25/56] Change type of items in `alternativeAliases` from String to RoomAlias --- .../element/android/libraries/matrix/api/room/MatrixRoomInfo.kt | 2 +- .../android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index b466a28da6..e335996cd0 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -31,7 +31,7 @@ data class MatrixRoomInfo( val isTombstoned: Boolean, val isFavorite: Boolean, val canonicalAlias: RoomAlias?, - val alternativeAliases: ImmutableList, + val alternativeAliases: ImmutableList, val currentUserMembership: CurrentUserMembership, val inviter: RoomMember?, val activeMembersCount: Long, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 7fcef163b6..1126d3dab9 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -39,7 +39,7 @@ class MatrixRoomInfoMapper { isTombstoned = it.isTombstoned, isFavorite = it.isFavourite, canonicalAlias = it.canonicalAlias?.let(::RoomAlias), - alternativeAliases = it.alternativeAliases.toImmutableList(), + alternativeAliases = it.alternativeAliases.map(::RoomAlias).toImmutableList(), currentUserMembership = it.membership.map(), inviter = it.inviter?.let(RoomMemberMapper::map), activeMembersCount = it.activeMembersCount.toLong(), diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 54b52c6fb7..8ff9d70bcc 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -520,7 +520,7 @@ fun aRoomInfo( isTombstoned: Boolean = false, isFavorite: Boolean = false, canonicalAlias: RoomAlias? = null, - alternativeAliases: List = emptyList(), + alternativeAliases: List = emptyList(), currentUserMembership: CurrentUserMembership = CurrentUserMembership.JOINED, inviter: RoomMember? = null, activeMembersCount: Long = 1, From 97f0b65c03775eb86ed57718c6a19572199fab8c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 13:59:17 +0200 Subject: [PATCH 26/56] Change type of items in `activeRoomCallParticipants` from String to UserId --- .../element/android/libraries/matrix/api/room/MatrixRoomInfo.kt | 2 +- .../android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt | 2 +- .../android/libraries/matrix/test/room/FakeMatrixRoom.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt index e335996cd0..b83c2c98d6 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt @@ -42,7 +42,7 @@ data class MatrixRoomInfo( val notificationCount: Long, val userDefinedNotificationMode: RoomNotificationMode?, val hasRoomCall: Boolean, - val activeRoomCallParticipants: ImmutableList, + val activeRoomCallParticipants: ImmutableList, val heroes: ImmutableList, val pinnedEventIds: ImmutableList, val creator: UserId?, diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt index 1126d3dab9..c7ed6c1205 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt @@ -50,7 +50,7 @@ class MatrixRoomInfoMapper { notificationCount = it.notificationCount.toLong(), userDefinedNotificationMode = it.cachedUserDefinedNotificationMode?.map(), hasRoomCall = it.hasRoomCall, - activeRoomCallParticipants = it.activeRoomCallParticipants.toImmutableList(), + activeRoomCallParticipants = it.activeRoomCallParticipants.map(::UserId).toImmutableList(), heroes = it.elementHeroes().toImmutableList(), pinnedEventIds = it.pinnedEventIds.map(::EventId).toImmutableList(), ) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt index 8ff9d70bcc..076baf5f2b 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt @@ -531,7 +531,7 @@ fun aRoomInfo( userDefinedNotificationMode: RoomNotificationMode? = null, hasRoomCall: Boolean = false, userPowerLevels: ImmutableMap = persistentMapOf(), - activeRoomCallParticipants: List = emptyList(), + activeRoomCallParticipants: List = emptyList(), heroes: List = emptyList(), pinnedEventIds: List = emptyList(), roomCreator: UserId? = null, From a60198a7167cc859f44c99be2a948035226f8c74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:10:01 +0200 Subject: [PATCH 27/56] Add unit test on MatrixRoomInfoMapper --- .../matrix/impl/fixtures/RustRoomInfo.kt | 4 +- .../impl/room/MatrixRoomInfoMapperTest.kt | 189 ++++++++++++++++++ .../matrix/impl/room/RoomInfoExtTest.kt | 2 +- 3 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt index e64dabf27a..b78780ee23 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt @@ -18,8 +18,8 @@ import org.matrix.rustcomponents.sdk.RoomNotificationMode fun aRustRoomInfo( id: String = A_ROOM_ID.value, - displayName: String = A_ROOM_NAME, - rawName: String = A_ROOM_NAME, + displayName: String? = A_ROOM_NAME, + rawName: String? = A_ROOM_NAME, topic: String? = null, avatarUrl: String? = null, isDirect: Boolean = false, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt new file mode 100644 index 0000000000..f0b02df6b7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -0,0 +1,189 @@ +/* + * 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.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomAlias +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.room.CurrentUserMembership +import io.element.android.libraries.matrix.api.room.MatrixRoomInfo +import io.element.android.libraries.matrix.api.room.RoomNotificationMode +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.room.member.aRustRoomMember +import io.element.android.libraries.matrix.impl.roomlist.aRustRoomInfo +import io.element.android.libraries.matrix.test.AN_AVATAR_URL +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_3 +import io.element.android.libraries.matrix.test.A_USER_ID_6 +import io.element.android.libraries.matrix.test.room.aRoomMember +import kotlinx.collections.immutable.toImmutableList +import kotlinx.collections.immutable.toImmutableMap +import kotlinx.collections.immutable.toPersistentList +import org.junit.Test +import org.matrix.rustcomponents.sdk.Membership +import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode + +class MatrixRoomInfoMapperTest { + @Test + fun `mapping of RustRoomInfo should map all the fields`() { + assertThat( + MatrixRoomInfoMapper().map( + aRustRoomInfo( + id = A_ROOM_ID.value, + displayName = "displayName", + rawName = "rawName", + topic = "topic", + avatarUrl = AN_AVATAR_URL, + isDirect = true, + isPublic = false, + isSpace = false, + isTombstoned = false, + isFavourite = false, + canonicalAlias = A_ROOM_ALIAS.value, + alternativeAliases = listOf(A_ROOM_ALIAS.value), + membership = Membership.JOINED, + inviter = aRustRoomMember(A_USER_ID), + heroes = listOf(aRoomHero()), + activeMembersCount = 2uL, + invitedMembersCount = 3uL, + joinedMembersCount = 4uL, + userPowerLevels = mapOf(A_USER_ID_6.value to 50L), + highlightCount = 10uL, + notificationCount = 11uL, + userDefinedNotificationMode = RustRoomNotificationMode.MUTE, + hasRoomCall = true, + activeRoomCallParticipants = listOf(A_USER_ID_3.value), + isMarkedUnread = false, + numUnreadMessages = 12uL, + numUnreadNotifications = 13uL, + numUnreadMentions = 14uL, + pinnedEventIds = listOf(AN_EVENT_ID.value), + ) + ) + ).isEqualTo( + MatrixRoomInfo( + id = A_ROOM_ID, + name = "displayName", + rawName = "rawName", + topic = "topic", + avatarUrl = AN_AVATAR_URL, + isDirect = true, + isPublic = false, + isSpace = false, + isTombstoned = false, + isFavorite = false, + canonicalAlias = A_ROOM_ALIAS, + alternativeAliases = listOf(A_ROOM_ALIAS).toImmutableList(), + currentUserMembership = CurrentUserMembership.JOINED, + inviter = aRoomMember(A_USER_ID), + activeMembersCount = 2L, + invitedMembersCount = 3L, + joinedMembersCount = 4L, + userPowerLevels = mapOf(A_USER_ID_6 to 50L).toImmutableMap(), + highlightCount = 10L, + notificationCount = 11L, + userDefinedNotificationMode = RoomNotificationMode.MUTE, + hasRoomCall = true, + activeRoomCallParticipants = listOf(A_USER_ID_3).toImmutableList(), + heroes = listOf( + MatrixUser( + userId = A_USER_ID, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) + ).toImmutableList(), + pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(), + ) + ) + } + + @Test + fun `mapping of RustRoomInfo with null members should map all the fields`() { + assertThat( + MatrixRoomInfoMapper().map( + aRustRoomInfo( + id = A_ROOM_ID.value, + displayName = null, + rawName = null, + topic = null, + avatarUrl = null, + isDirect = false, + isPublic = true, + isSpace = false, + isTombstoned = false, + isFavourite = true, + canonicalAlias = null, + alternativeAliases = emptyList(), + membership = Membership.INVITED, + inviter = null, + heroes = listOf(aRoomHero()), + activeMembersCount = 2uL, + invitedMembersCount = 3uL, + joinedMembersCount = 4uL, + userPowerLevels = emptyMap(), + highlightCount = 10uL, + notificationCount = 11uL, + userDefinedNotificationMode = null, + hasRoomCall = false, + activeRoomCallParticipants = emptyList(), + isMarkedUnread = true, + numUnreadMessages = 12uL, + numUnreadNotifications = 13uL, + numUnreadMentions = 14uL, + pinnedEventIds = emptyList(), + ) + ) + ).isEqualTo( + MatrixRoomInfo( + id = A_ROOM_ID, + name = null, + rawName = null, + topic = null, + avatarUrl = null, + isDirect = false, + isPublic = true, + isSpace = false, + isTombstoned = false, + isFavorite = true, + canonicalAlias = null, + alternativeAliases = emptyList().toPersistentList(), + currentUserMembership = CurrentUserMembership.INVITED, + inviter = null, + activeMembersCount = 2L, + invitedMembersCount = 3L, + joinedMembersCount = 4L, + userPowerLevels = emptyMap().toImmutableMap(), + highlightCount = 10L, + notificationCount = 11L, + userDefinedNotificationMode = null, + hasRoomCall = false, + activeRoomCallParticipants = emptyList().toImmutableList(), + heroes = emptyList().toImmutableList(), + pinnedEventIds = emptyList().toPersistentList(), + ) + ) + } + + @Test + fun `mapping Membership`() { + assertThat(Membership.INVITED.map()).isEqualTo(CurrentUserMembership.INVITED) + assertThat(Membership.JOINED.map()).isEqualTo(CurrentUserMembership.JOINED) + assertThat(Membership.LEFT.map()).isEqualTo(CurrentUserMembership.LEFT) + } + + @Test + fun `mapping RoomNotificationMode`() { + assertThat(RustRoomNotificationMode.ALL_MESSAGES.map()).isEqualTo(RoomNotificationMode.ALL_MESSAGES) + assertThat(RustRoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY.map()).isEqualTo(RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) + assertThat(RustRoomNotificationMode.MUTE.map()).isEqualTo(RoomNotificationMode.MUTE) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 7c5c873155..7d671d0972 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -65,7 +65,7 @@ class RoomInfoExtTest { } } -private fun aRoomHero( +internal fun aRoomHero( userId: UserId = A_USER_ID, ): RoomHero { return RoomHero( From 8efdf6604b8f88aef9d7c4961db1be231a4a15d1 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:11:41 +0200 Subject: [PATCH 28/56] Add unit test on ReceiptType.toRustReceiptType() --- .../impl/timeline/ReceiptTypeMapperKtTest.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.kt new file mode 100644 index 0000000000..5ba93d26ce --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/ReceiptTypeMapperKtTest.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.timeline + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.timeline.ReceiptType +import org.junit.Test +import org.matrix.rustcomponents.sdk.ReceiptType as RustReceiptType + +class ReceiptTypeMapperKtTest { + @Test + fun toRustReceiptType() { + assertThat(ReceiptType.READ.toRustReceiptType()).isEqualTo(RustReceiptType.READ) + assertThat(ReceiptType.READ_PRIVATE.toRustReceiptType()).isEqualTo(RustReceiptType.READ_PRIVATE) + assertThat(ReceiptType.FULLY_READ.toRustReceiptType()).isEqualTo(RustReceiptType.FULLY_READ) + } +} From 2514a7f71063325c61e5cac775378f20b31c92cd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:13:18 +0200 Subject: [PATCH 29/56] Add unit test on toRoomType --- .../matrix/impl/room/RoomTypeKtTest.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.kt new file mode 100644 index 0000000000..541598781e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomTypeKtTest.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.room + +import io.element.android.libraries.matrix.api.room.RoomType +import org.junit.Test + +class RoomTypeKtTest { + @Test + fun toRoomType() { + assert(null.toRoomType() == RoomType.Room) + assert("m.space".toRoomType() == RoomType.Space) + assert("m.other".toRoomType() == RoomType.Other("m.other")) + } +} From 88004db53177b702d12e6d2e052d22fb38add4c3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:14:59 +0200 Subject: [PATCH 30/56] Add unit test on UserProfileMapper --- .../impl/usersearch/UserProfileMapperTest.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt new file mode 100644 index 0000000000..0564186a78 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt @@ -0,0 +1,22 @@ +/* + * 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.usersearch + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.UserProfile + +class UserProfileMapperTest { + @Test + fun map() { + assertThat(UserProfileMapper.map(UserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) + .isEqualTo(MatrixUser(A_USER_ID, "displayName", "avatarUrl")) + } +} From e2a4fbbd61ef6ac46cbb4ea21936306e588fc4ce Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:18:54 +0200 Subject: [PATCH 31/56] Add unit test on UserSearchResultMapper --- .../usersearch/UserSearchResultMapperTest.kt | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt new file mode 100644 index 0000000000..17ce3836ca --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt @@ -0,0 +1,55 @@ +/* + * 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.usersearch + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.A_USER_ID +import kotlinx.collections.immutable.toImmutableList +import org.junit.Test +import org.matrix.rustcomponents.sdk.SearchUsersResults +import org.matrix.rustcomponents.sdk.UserProfile + +class UserSearchResultMapperTest { + @Test + fun `map limited list`() { + assertThat( + UserSearchResultMapper.map( + SearchUsersResults( + results = listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + limited = true, + ) + ) + ) + .isEqualTo( + MatrixSearchUserResults( + results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(), + limited = true, + ) + ) + } + + @Test + fun `map not limited list`() { + assertThat( + UserSearchResultMapper.map( + SearchUsersResults( + listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + false, + ) + ) + ) + .isEqualTo( + MatrixSearchUserResults( + results = listOf(MatrixUser(A_USER_ID, "displayName", "avatarUrl")).toImmutableList(), + limited = false, + ) + ) + } +} From 9ae7e998c00c04e4c3b8b36ebbc48363aaa9c615 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:22:11 +0200 Subject: [PATCH 32/56] Add unit test on SyncServiceState.toSyncState --- .../matrix/impl/sync/AppStateMapperKtTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.kt new file mode 100644 index 0000000000..54fc06f8f1 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/sync/AppStateMapperKtTest.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.sync + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.sync.SyncState +import org.junit.Test +import org.matrix.rustcomponents.sdk.SyncServiceState + +class AppStateMapperKtTest { + @Test + fun toSyncState() { + assertThat(SyncServiceState.IDLE.toSyncState()).isEqualTo(SyncState.Idle) + assertThat(SyncServiceState.RUNNING.toSyncState()).isEqualTo(SyncState.Running) + assertThat(SyncServiceState.TERMINATED.toSyncState()).isEqualTo(SyncState.Terminated) + assertThat(SyncServiceState.ERROR.toSyncState()).isEqualTo(SyncState.Error) + } +} From 2d274a9b3486c242630bfa5bb227e37353ba2fdf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:48:07 +0200 Subject: [PATCH 33/56] Add unit test on RoomDescriptionMapper --- .../roomdirectory/RoomDescriptionMapper.kt | 14 +++-- .../RoomDescriptionMapperTest.kt | 60 +++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt index e91242f165..267de74ba7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapper.kt @@ -21,13 +21,17 @@ class RoomDescriptionMapper { topic = roomDescription.topic, avatarUrl = roomDescription.avatarUrl, alias = roomDescription.alias?.let(::RoomAlias), - joinRule = when (roomDescription.joinRule) { - PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC - PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK - null -> RoomDescription.JoinRule.UNKNOWN - }, + joinRule = roomDescription.joinRule.map(), isWorldReadable = roomDescription.isWorldReadable, numberOfMembers = roomDescription.joinedMembers.toLong(), ) } } + +internal fun PublicRoomJoinRule?.map(): RoomDescription.JoinRule { + return when (this) { + PublicRoomJoinRule.PUBLIC -> RoomDescription.JoinRule.PUBLIC + PublicRoomJoinRule.KNOCK -> RoomDescription.JoinRule.KNOCK + null -> RoomDescription.JoinRule.UNKNOWN + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt new file mode 100644 index 0000000000..307cc33b54 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt @@ -0,0 +1,60 @@ +/* + * 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 com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.libraries.matrix.test.roomdirectory.aRoomDescription +import org.junit.Test +import org.matrix.rustcomponents.sdk.PublicRoomJoinRule +import org.matrix.rustcomponents.sdk.RoomDescription as RustRoomDescription + +class RoomDescriptionMapperTest { + @Test + fun map() { + assertThat(RoomDescriptionMapper().map(aRustRoomDescription())).isEqualTo( + aRoomDescription( + roomId = A_ROOM_ID, + name = "name", + topic = "topic", + alias = A_ROOM_ALIAS, + avatarUrl = "avatarUrl", + joinRule = RoomDescription.JoinRule.PUBLIC, + isWorldReadable = true, + joinedMembers = 2L + ) + ) + } + + @Test + fun mapWithNullAlias() { + assertThat(RoomDescriptionMapper().map(aRustRoomDescription().copy(alias = null)).alias).isNull() + } + + @Test + fun `map join rule`() { + assertThat(PublicRoomJoinRule.PUBLIC.map()).isEqualTo(RoomDescription.JoinRule.PUBLIC) + assertThat(PublicRoomJoinRule.KNOCK.map()).isEqualTo(RoomDescription.JoinRule.KNOCK) + assertThat(null.map()).isEqualTo(RoomDescription.JoinRule.UNKNOWN) + } +} + +internal fun aRustRoomDescription(): RustRoomDescription { + return RustRoomDescription( + roomId = A_ROOM_ID.value, + name = "name", + topic = "topic", + alias = A_ROOM_ALIAS.value, + avatarUrl = "avatarUrl", + joinRule = PublicRoomJoinRule.PUBLIC, + isWorldReadable = true, + joinedMembers = 2u + ) +} From 7b75affe2ddd06a3f66175d7049162e3a368e235 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:54:08 +0200 Subject: [PATCH 34/56] Add unit test on RoomPreviewMapper --- .../room/preview/RoomPreviewMapperTest.kt | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt new file mode 100644 index 0000000000..3e0fea4bdc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt @@ -0,0 +1,96 @@ +/* + * 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.preview + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomType +import io.element.android.libraries.matrix.api.room.preview.RoomPreview +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.junit.Test +import org.matrix.rustcomponents.sdk.RoomPreview as RustRoomPreview + +class RoomPreviewMapperTest { + @Test + fun `map should map values 1`() { + assertThat( + RoomPreviewMapper.map( + aRustRoomPreview( + isJoined = false, + isInvited = false, + ) + ) + ).isEqualTo( + RoomPreview( + roomId = A_ROOM_ID, + canonicalAlias = A_ROOM_ALIAS, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numberOfJoinedMembers = 1L, + roomType = RoomType.Room, + isHistoryWorldReadable = true, + isJoined = false, + isInvited = false, + isPublic = true, + canKnock = true, + ) + ) + } + + @Test + fun `map should map values 2`() { + assertThat( + RoomPreviewMapper.map( + aRustRoomPreview( + canonicalAlias = null, + isPublic = false, + canKnock = false, + ) + ) + ).isEqualTo( + RoomPreview( + roomId = A_ROOM_ID, + canonicalAlias = null, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numberOfJoinedMembers = 1L, + roomType = RoomType.Room, + isHistoryWorldReadable = true, + isJoined = true, + isInvited = true, + isPublic = false, + canKnock = false, + ) + ) + } +} + +internal fun aRustRoomPreview( + canonicalAlias: String? = A_ROOM_ALIAS.value, + isJoined: Boolean = true, + isInvited: Boolean = true, + isPublic: Boolean = true, + canKnock: Boolean = true, +): RustRoomPreview { + return RustRoomPreview( + roomId = A_ROOM_ID.value, + canonicalAlias = canonicalAlias, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numJoinedMembers = 1u, + roomType = null, + isHistoryWorldReadable = true, + isJoined = isJoined, + isInvited = isInvited, + isPublic = isPublic, + canKnock = canKnock, + ) +} From b237485a6c59ae9bbf4d5135493500fc3add6cea Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 14:55:55 +0200 Subject: [PATCH 35/56] Add unit test on AssetType.toInner() --- .../impl/room/location/AssetTypeKtTest.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.kt new file mode 100644 index 0000000000..78807bc324 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/location/AssetTypeKtTest.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.room.location + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.location.AssetType +import org.junit.Test + +class AssetTypeKtTest { + @Test + fun toInner() { + assertThat(AssetType.SENDER.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.SENDER) + assertThat(AssetType.PIN.toInner()).isEqualTo(org.matrix.rustcomponents.sdk.AssetType.PIN) + } +} From 98f6effd8d06d5711604c77cf825669273f25969 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 15:00:30 +0200 Subject: [PATCH 36/56] Add unit test on RoomMemberMapper --- .../impl/room/member/RoomMemberMapperTest.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt new file mode 100644 index 0000000000..dcf3ed5ee1 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberMapperTest.kt @@ -0,0 +1,33 @@ +/* + * 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.member + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.room.RoomMember +import io.element.android.libraries.matrix.api.room.RoomMembershipState +import org.junit.Test +import uniffi.matrix_sdk.RoomMemberRole +import org.matrix.rustcomponents.sdk.MembershipState as RustMembershipState + +class RoomMemberMapperTest { + @Test + fun mapRole() { + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.USER)).isEqualTo(RoomMember.Role.USER) + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.MODERATOR)).isEqualTo(RoomMember.Role.MODERATOR) + assertThat(RoomMemberMapper.mapRole(RoomMemberRole.ADMINISTRATOR)).isEqualTo(RoomMember.Role.ADMIN) + } + + @Test + fun mapMembership() { + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.BAN)).isEqualTo(RoomMembershipState.BAN) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.INVITE)).isEqualTo(RoomMembershipState.INVITE) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.JOIN)).isEqualTo(RoomMembershipState.JOIN) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.KNOCK)).isEqualTo(RoomMembershipState.KNOCK) + assertThat(RoomMemberMapper.mapMembership(RustMembershipState.LEAVE)).isEqualTo(RoomMembershipState.LEAVE) + } +} From 26260aed9fd0fb7154a77aabf9ce02c80a5bea60 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 16:47:11 +0200 Subject: [PATCH 37/56] Fix compilation issue after rebase. --- .../libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt index f0b02df6b7..ce04469ff8 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -67,6 +67,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = listOf(AN_EVENT_ID.value), + roomCreator = A_USER_ID.value, ) ) ).isEqualTo( @@ -102,6 +103,7 @@ class MatrixRoomInfoMapperTest { ) ).toImmutableList(), pinnedEventIds = listOf(AN_EVENT_ID).toPersistentList(), + creator = A_USER_ID, ) ) } @@ -140,6 +142,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = emptyList(), + roomCreator = null, ) ) ).isEqualTo( @@ -169,6 +172,7 @@ class MatrixRoomInfoMapperTest { activeRoomCallParticipants = emptyList().toImmutableList(), heroes = emptyList().toImmutableList(), pinnedEventIds = emptyList().toPersistentList(), + creator = null, ) ) } From 2ee71b5dee22833b20bf688daf22f449ca525efc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:05:11 +0200 Subject: [PATCH 38/56] Add unit test on LastForwardIndicatorsPostProcessor --- .../impl/timeline/postprocessor/Fixtures.kt | 46 +++++++++ .../LastForwardIndicatorsPostProcessorTest.kt | 94 +++++++++++++++++++ .../RoomBeginningPostProcessorTest.kt | 25 ----- 3 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt new file mode 100644 index 0000000000..16acfd718f --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange +import io.element.android.libraries.matrix.api.timeline.item.event.OtherState +import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent +import io.element.android.libraries.matrix.api.timeline.item.event.StateContent +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.A_USER_ID_2 +import io.element.android.libraries.matrix.test.timeline.aMessageContent +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem + +internal val roomCreateEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.create"), + event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate)) +) +internal val roomCreatorJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED)) +) +internal val otherMemberJoinEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.member_other"), + event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) +) +internal val messageEvent = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.message"), + event = anEventTimelineItem(content = aMessageContent("hi")) +) +internal val messageEvent2 = MatrixTimelineItem.Event( + uniqueId = UniqueId("m.room.message2"), + event = anEventTimelineItem(content = aMessageContent("hello")) +) +internal val dayEvent = MatrixTimelineItem.Virtual( + uniqueId = UniqueId("day"), + virtual = VirtualTimelineItem.DayDivider(0), +) + diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt new file mode 100644 index 0000000000..398b2f5883 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LastForwardIndicatorsPostProcessorTest.kt @@ -0,0 +1,94 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import org.junit.Test + +class LastForwardIndicatorsPostProcessorTest { + @Test + fun `LastForwardIndicatorsPostProcessor does not alter the items with mode not FOCUSED_ON_EVENT`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.LIVE) + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly(messageEvent) + } + + @Test + fun `LastForwardIndicatorsPostProcessor does not alter the items with mode FOCUSED_ON_EVENT but timeline not initialized`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(messageEvent), false) + assertThat(result).containsExactly(messageEvent) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly( + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items on empty list`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + val result = sut.process(listOf(), true) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_fake_id"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items but does not alter the list if called a second time`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + // Process a first time + sut.process(listOf(messageEvent), true) + // Process a second time with the same Event + val result = sut.process(listOf(messageEvent), true) + assertThat(result).containsExactly( + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } + + @Test + fun `LastForwardIndicatorsPostProcessor add virtual items each time it is called with new Events`() { + val sut = LastForwardIndicatorsPostProcessor(Timeline.Mode.FOCUSED_ON_EVENT) + // Process a first time + sut.process(listOf(dayEvent, messageEvent), true) + // Process a second time with the same Event + val result = sut.process(listOf(dayEvent, messageEvent, messageEvent2), true) + assertThat(result).containsExactly( + dayEvent, + messageEvent, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ), + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("last_forward_indicator_${messageEvent2.uniqueId}"), + virtual = VirtualTimelineItem.LastForwardIndicator + ) + ) + } +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index fadc174cd1..41d175b348 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -8,36 +8,11 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor import com.google.common.truth.Truth.assertThat -import io.element.android.libraries.matrix.api.core.UniqueId -import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.Timeline -import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange -import io.element.android.libraries.matrix.api.timeline.item.event.OtherState -import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent -import io.element.android.libraries.matrix.api.timeline.item.event.StateContent import io.element.android.libraries.matrix.test.A_USER_ID -import io.element.android.libraries.matrix.test.A_USER_ID_2 -import io.element.android.libraries.matrix.test.timeline.aMessageContent -import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem import org.junit.Test class RoomBeginningPostProcessorTest { - private val roomCreateEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.create"), - event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate)) - ) - private val roomCreatorJoinEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.member"), - event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED)) - ) - private val otherMemberJoinEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.member_other"), - event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED)) - ) - private val messageEvent = MatrixTimelineItem.Event( - uniqueId = UniqueId("m.room.message"), - event = anEventTimelineItem(content = aMessageContent("hi")) - ) @Test fun `processor returns empty list when empty list is provided`() { From 32c210118422f81b973802150d96e828339fa3bd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:15:09 +0200 Subject: [PATCH 39/56] Add unit test on LoadingIndicatorsPostProcessor --- libraries/matrix/impl/build.gradle.kts | 1 + .../LoadingIndicatorsPostProcessorTest.kt | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 76eb030615..5d386169ad 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -48,6 +48,7 @@ dependencies { testImplementation(libs.test.robolectric) testImplementation(projects.libraries.matrix.test) testImplementation(projects.services.analytics.test) + testImplementation(projects.services.toolbox.test) testImplementation(projects.tests.testutils) testImplementation(libs.coroutines.test) testImplementation(libs.test.turbine) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt new file mode 100644 index 0000000000..4859355917 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/LoadingIndicatorsPostProcessorTest.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline.postprocessor + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.UniqueId +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import org.junit.Test + +class LoadingIndicatorsPostProcessorTest { + @Test + fun `LoadingIndicatorsPostProcessor does not alter the items is the timeline is not initialized`() { + val sut = LoadingIndicatorsPostProcessor(FakeSystemClock()) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = false, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly(messageEvent, messageEvent2) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the top of the list if hasMoreToLoadBackward is true`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = false, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + messageEvent, + messageEvent2, + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom of the list if hasMoreToLoadForward is true`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = false, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + messageEvent, + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("ForwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.FORWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor adds Loading indicator at the bottom and at the top of the list`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(messageEvent, messageEvent2), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + messageEvent, + messageEvent2, + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("ForwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.FORWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } + + @Test + fun `LoadingIndicatorsPostProcessor only adds 1 Loading indicator if there is no items in the list`() { + val clock = FakeSystemClock() + val sut = LoadingIndicatorsPostProcessor(clock) + val result = sut.process( + items = listOf(), + isTimelineInitialized = true, + hasMoreToLoadBackward = true, + hasMoreToLoadForward = true, + ) + assertThat(result).containsExactly( + MatrixTimelineItem.Virtual( + uniqueId = UniqueId("BackwardLoadingIndicator"), + virtual = VirtualTimelineItem.LoadingIndicator( + direction = Timeline.PaginationDirection.BACKWARDS, + timestamp = clock.epochMillis() + ) + ), + ) + } +} From 51e661013e149a6ba968ca96e7b93e232799ef45 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:17:17 +0200 Subject: [PATCH 40/56] Add unit test on PollKind mapper --- .../matrix/impl/poll/PollKindKtTest.kt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt new file mode 100644 index 0000000000..97f049bcb7 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2023, 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.poll + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.poll.PollKind +import org.junit.Test +import org.matrix.rustcomponents.sdk.PollKind as RustPollKind + + +class PollKindKtTest { + @Test + fun `map should return Disclosed when RustPollKind is Disclosed`() { + val pollKind = RustPollKind.DISCLOSED.map() + assertThat(pollKind).isEqualTo(PollKind.Disclosed) + } + + @Test + fun `map should return Undisclosed when RustPollKind is Undisclosed`() { + val pollKind = RustPollKind.UNDISCLOSED.map() + assertThat(pollKind).isEqualTo(PollKind.Undisclosed) + } + + @Test + fun `toInner should return DISCLOSED when PollKind is Disclosed`() { + val rustPollKind = PollKind.Disclosed.toInner() + assertThat(rustPollKind).isEqualTo(RustPollKind.DISCLOSED) + } + + @Test + fun `toInner should return UNDISCLOSED when PollKind is Undisclosed`() { + val rustPollKind = PollKind.Undisclosed.toInner() + assertThat(rustPollKind).isEqualTo(RustPollKind.UNDISCLOSED) + } +} From e111d78a24c43a19de1ebc846de21c89ba70a636 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:35:22 +0200 Subject: [PATCH 41/56] Add missing test for RoomListEntriesUpdate.Reset --- .../impl/roomlist/RoomSummaryListProcessorTest.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 93096ee227..45a023d636 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 @@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomListItem 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 io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled import kotlinx.coroutines.flow.MutableStateFlow @@ -148,6 +149,18 @@ class RoomSummaryListProcessorTest { assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID) } + @Test + fun `Rest removes all entries and add the provided ones`() = runTest { + summaries.value = listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(A_ROOM_ID_2)) + val processor = createProcessor() + val index = 0 + + processor.postUpdate(listOf(RoomListEntriesUpdate.Reset(listOf(FakeRustRoomListItem(A_ROOM_ID_3))))) + + assertThat(summaries.value.count()).isEqualTo(1) + assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_3) + } + private fun TestScope.createProcessor() = RoomSummaryListProcessor( summaries, fakeRoomListService, From 525186cb18e6afa4ed138bba81122eaed5aad732 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:41:29 +0200 Subject: [PATCH 42/56] Exclude RoomListEntriesUpdate.describe() from coverage, it's only used to debug the app. --- .../libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt index d0ed9bb777..e03c8529c7 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListEntriesUpdateExt.kt @@ -7,8 +7,11 @@ package io.element.android.libraries.matrix.impl.roomlist +import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate +@Suppress("unused") +@ExcludeFromCoverage internal fun RoomListEntriesUpdate.describe(): String { return when (this) { is RoomListEntriesUpdate.Set -> { From db311c4cccba1ec1c03e2304a8ffa38210bce54b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:44:34 +0200 Subject: [PATCH 43/56] Add unit test on DefaultUserServerResolver --- .../server/DefaultUserServerResolverTest.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.kt new file mode 100644 index 0000000000..b9778190ef --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/server/DefaultUserServerResolverTest.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.server + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.FakeMatrixClient +import org.junit.Test + +class DefaultUserServerResolverTest { + @Test + fun resolve() { + // Given + val userServerResolver = DefaultUserServerResolver(FakeMatrixClient( + userIdServerNameLambda = { "dummy.org" } + )) + + // When + val result = userServerResolver.resolve() + + // Then + assertThat(result).isEqualTo("dummy.org") + } +} From c26e889d45c67f0e6a46d9fd78bf97aa863112a2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 17:56:00 +0200 Subject: [PATCH 44/56] Add unit test on DefaultPassphraseGenerator --- .../keys/DefaultPassphraseGeneratorTest.kt | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.kt new file mode 100644 index 0000000000..e4ac3b591e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/keys/DefaultPassphraseGeneratorTest.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.keys + +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class DefaultPassphraseGeneratorTest { + @Test + fun `check that generated passphrase has the expected length`() { + val passphraseGenerator = DefaultPassphraseGenerator() + val passphrase = passphraseGenerator.generatePassphrase() + assertThat(passphrase!!.length).isEqualTo(342) + } +} From eea976bb18008da16209a7f5e640f42f385c900d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 18:09:12 +0200 Subject: [PATCH 45/56] Add unit test on toSessionData --- .../matrix/impl/mapper/SessionKtTest.kt | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt 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 new file mode 100644 index 0000000000..aac34dfdab --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/mapper/SessionKtTest.kt @@ -0,0 +1,98 @@ +/* + * 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.mapper + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.impl.paths.SessionPaths +import io.element.android.libraries.matrix.test.A_DEVICE_ID +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL_2 +import io.element.android.libraries.matrix.test.A_SECRET +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.sessionstorage.api.LoginType +import org.junit.Test +import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion +import java.io.File + +class SessionKtTest { + @Test + fun `toSessionData compute the expected result`() { + val result = aRustSession().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).isEqualTo("refreshToken") + 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 `toSessionData can change the validity of the token`() { + val result = aRustSession().toSessionData( + isTokenValid = false, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = null, + ) + assertThat(result.isTokenValid).isFalse() + } + + @Test + fun `toSessionData can override the value of the homeserver url`() { + val result = aRustSession().toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = A_HOMESERVER_URL_2, + ) + assertThat(result.homeserverUrl).isEqualTo(A_HOMESERVER_URL_2) + } + + @Test + fun `toSessionData copy the sliding sync url if present`() { + val result = aRustSession( + proxy = SlidingSyncVersion.Proxy("proxyUrl") + ).toSessionData( + isTokenValid = true, + loginType = LoginType.PASSWORD, + passphrase = A_SECRET, + sessionPaths = SessionPaths(File("/a/file"), File("/a/cache")), + homeserverUrl = A_HOMESERVER_URL_2, + ) + assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl") + } +} + +internal fun aRustSession( + proxy: SlidingSyncVersion = SlidingSyncVersion.None +): Session { + return Session( + accessToken = "accessToken", + refreshToken = "refreshToken", + userId = A_USER_ID.value, + deviceId = A_DEVICE_ID.value, + homeserverUrl = A_HOMESERVER_URL, + oidcData = null, + slidingSyncVersion = proxy, + ) +} From 6cb4d10375bcdcef9abe5b781fcc3a4b77b7f17b Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 19:43:37 +0200 Subject: [PATCH 46/56] Fix typo --- .../matrix/impl/roomlist/RoomSummaryListProcessorTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 45a023d636..d4b347af44 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 @@ -150,7 +150,7 @@ class RoomSummaryListProcessorTest { } @Test - fun `Rest removes all entries and add the provided ones`() = runTest { + fun `Reset removes all entries and add the provided ones`() = runTest { summaries.value = listOf(aRoomSummaryFilled(roomId = A_ROOM_ID), aRoomSummaryFilled(A_ROOM_ID_2)) val processor = createProcessor() val index = 0 From 619841fc8029b0d2c93e0b0375da3861c247f4c6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 19:48:21 +0200 Subject: [PATCH 47/56] Add unit test on MatrixTimelineDiffProcessor --- .../timeline/MatrixTimelineDiffProcessor.kt | 9 +- .../MatrixTimelineDiffProcessorTest.kt | 199 ++++++++++++++++++ 2 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index 47be0fd07a..3523823d5e 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiff +import org.matrix.rustcomponents.sdk.TimelineDiffInterface import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -36,7 +36,7 @@ internal class MatrixTimelineDiffProcessor( } } - suspend fun postDiffs(diffs: List) { + suspend fun postDiffs(diffs: List) { updateTimelineItems { Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}") diffs.forEach { diff -> @@ -52,7 +52,7 @@ internal class MatrixTimelineDiffProcessor( timelineItems.value = mutableTimelineItems } - private fun MutableList.applyDiff(diff: TimelineDiff) { + private fun MutableList.applyDiff(diff: TimelineDiffInterface) { when (diff.change()) { TimelineChange.APPEND -> { val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return @@ -100,7 +100,8 @@ internal class MatrixTimelineDiffProcessor( clear() } TimelineChange.TRUNCATE -> { - // Not supported + val index = diff.truncate() ?: return + subList(index.toInt(), size).clear() } } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt new file mode 100644 index 0000000000..84ce6e61f9 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -0,0 +1,199 @@ +/* + * Copyright 2024 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only + * Please see LICENSE in the repository root for full details. + */ + +package io.element.android.libraries.matrix.impl.timeline + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper +import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper +import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper +import io.element.android.libraries.matrix.test.A_UNIQUE_ID +import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2 +import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.matrix.rustcomponents.sdk.EventTimelineItem +import org.matrix.rustcomponents.sdk.InsertData +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SetData +import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiffInterface +import org.matrix.rustcomponents.sdk.TimelineItem +import org.matrix.rustcomponents.sdk.VirtualTimelineItem + +open class FakeTimelineDiff( + private val change: TimelineChange, + private val item: TimelineItem? = FakeTimelineItem() +) : TimelineDiffInterface { + override fun change() = change + override fun append(): List? = item?.let { listOf(it) } + override fun insert(): InsertData? = item?.let { InsertData(1u, it) } + override fun pushBack(): TimelineItem? = item + override fun pushFront(): TimelineItem? = item + override fun remove(): UInt? = 1u + override fun reset(): List? = item?.let { listOf(it) } + override fun set(): SetData? = item?.let { SetData(1u, it) } + override fun truncate(): UInt? = 1u +} + +class MatrixTimelineDiffProcessorTest { + private val timelineItems = MutableStateFlow>(emptyList()) + + private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem()) + private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem()) + + @Test + fun `Append adds new entries at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.APPEND))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + ) + } + + @Test + fun `PushBack adds a new entry at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_BACK))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + ) + } + + @Test + fun `PushFront inserts a new entry at the start of the list`() = runTest { + timelineItems.value = listOf(anEvent) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_FRONT))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + MatrixTimelineItem.Other, + anEvent, + ) + } + + @Test + fun `Set replaces an entry at some index`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.SET))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other + ) + } + + @Test + fun `Insert inserts a new entry at the provided index`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.INSERT))) + assertThat(timelineItems.value.count()).isEqualTo(3) + assertThat(timelineItems.value).containsExactly( + anEvent, + MatrixTimelineItem.Other, + anEvent2, + ) + } + + @Test + fun `Remove removes an entry at some index`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.REMOVE))) + assertThat(timelineItems.value.count()).isEqualTo(2) + assertThat(timelineItems.value).containsExactly( + anEvent, + anEvent2, + ) + } + + @Test + fun `PopBack removes an entry at the end of the list`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_BACK))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent, + ) + } + + @Test + fun `PopFront removes an entry at the start of the list`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_FRONT))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent2, + ) + } + + @Test + fun `Clear removes all the entries`() = runTest { + timelineItems.value = listOf(anEvent, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.CLEAR))) + assertThat(timelineItems.value).isEmpty() + } + + @Test + fun `Truncate removes all entries after the provided length`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.TRUNCATE))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + anEvent, + ) + } + + @Test + fun `Reset removes all entries and add the provided ones`() = runTest { + timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) + val processor = createProcessor() + processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.RESET))) + assertThat(timelineItems.value.count()).isEqualTo(1) + assertThat(timelineItems.value).containsExactly( + MatrixTimelineItem.Other, + ) + } + + private fun TestScope.createProcessor(): MatrixTimelineDiffProcessor { + val timelineEventContentMapper = TimelineEventContentMapper() + val timelineItemMapper = MatrixTimelineItemMapper( + fetchDetailsForEvent = { _ -> Result.success(Unit) }, + coroutineScope = this, + virtualTimelineItemMapper = VirtualTimelineItemMapper(), + eventTimelineItemMapper = EventTimelineItemMapper( + contentMapper = timelineEventContentMapper + ) + ) + return MatrixTimelineDiffProcessor( + timelineItems, + timelineItemFactory = timelineItemMapper, + ) + } +} + +class FakeTimelineItem : TimelineItem(NoPointer) { + override fun asEvent(): EventTimelineItem? = null + override fun asVirtual(): VirtualTimelineItem? = null + override fun fmtDebug(): String = "fmtDebug" + override fun uniqueId(): String = "uniqueId" +} From 5de84f6ad8f7a8bdfc9f78ec0a299f82c28f80da Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 20:25:53 +0200 Subject: [PATCH 48/56] Use aSessionData() from the test module. And fix typo. --- features/rageshake/impl/build.gradle.kts | 1 + .../impl/reporter/DefaultBugReporterTest.kt | 24 ++++--------------- .../signedout/impl/SignedOutStateProvider.kt | 9 ++++--- .../sessionstorage/test/SessionData.kt | 8 +++---- 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/features/rageshake/impl/build.gradle.kts b/features/rageshake/impl/build.gradle.kts index 9d15043804..2ba2f1767d 100644 --- a/features/rageshake/impl/build.gradle.kts +++ b/features/rageshake/impl/build.gradle.kts @@ -55,6 +55,7 @@ dependencies { testImplementation(libs.test.mockk) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.features.rageshake.test) testImplementation(projects.tests.testutils) testImplementation(projects.services.toolbox.test) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt index 45aaf6eeda..a30112034e 100755 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterTest.kt @@ -17,9 +17,8 @@ import io.element.android.libraries.matrix.test.FakeSdkMetadata import io.element.android.libraries.matrix.test.core.aBuildMeta import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService import io.element.android.libraries.network.useragent.DefaultUserAgentProvider -import io.element.android.libraries.sessionstorage.api.LoginType -import io.element.android.libraries.sessionstorage.api.SessionData 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 @@ -94,7 +93,7 @@ class DefaultBugReporterTest { server.start() val mockSessionStore = InMemorySessionStore().apply { - storeData(mockSessionData("@foo:eample.com", "ABCDEFGH")) + storeData(aSessionData(sessionId = "@foo:example.com", deviceId = "ABCDEFGH")) } val buildMeta = aBuildMeta() @@ -143,7 +142,7 @@ class DefaultBugReporterTest { assertThat(foundValues["can_contact"]).isEqualTo("true") assertThat(foundValues["device_id"]).isEqualTo("ABCDEFGH") assertThat(foundValues["sdk_sha"]).isEqualTo("123456789") - assertThat(foundValues["user_id"]).isEqualTo("@foo:eample.com") + assertThat(foundValues["user_id"]).isEqualTo("@foo:example.com") assertThat(foundValues["text"]).isEqualTo("a bug occurred") assertThat(foundValues["device_keys"]).isEqualTo("curve25519:CURVECURVECURVE, ed25519:EDKEYEDKEYEDKY") @@ -163,7 +162,7 @@ class DefaultBugReporterTest { server.start() val mockSessionStore = InMemorySessionStore().apply { - storeData(mockSessionData("@foo:eample.com", "ABCDEFGH")) + storeData(aSessionData("@foo:example.com", "ABCDEFGH")) } val buildMeta = aBuildMeta() @@ -267,21 +266,6 @@ class DefaultBugReporterTest { return foundValues } - private fun mockSessionData(userId: String, deviceId: String) = SessionData( - userId = userId, - deviceId = deviceId, - homeserverUrl = "example.com", - accessToken = "AA", - isTokenValid = true, - loginType = LoginType.DIRECT, - loginTimestamp = null, - oidcData = null, - refreshToken = null, - slidingSyncProxy = null, - passphrase = null, - sessionPath = "session", - cachePath = "cache", - ) @Test fun `test sendBugReport error`() = runTest { val server = MockWebServer() diff --git a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt index 9221fb2e33..b6cdaaaa0e 100644 --- a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt +++ b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutStateProvider.kt @@ -8,7 +8,6 @@ package io.element.android.features.signedout.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData @@ -20,18 +19,18 @@ open class SignedOutStateProvider : PreviewParameterProvider { ) } -fun aSignedOutState() = SignedOutState( +private fun aSignedOutState() = SignedOutState( appName = "AppName", signedOutSession = aSessionData(), eventSink = {}, ) -fun aSessionData( - sessionId: SessionId = SessionId("@alice:server.org"), +private fun aSessionData( + sessionId: String = "@alice:server.org", isTokenValid: Boolean = false, ): SessionData { return SessionData( - userId = sessionId.value, + userId = sessionId, deviceId = "aDeviceId", accessToken = "anAccessToken", refreshToken = "aRefreshToken", 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 8b3a0e5b26..ad62337ae6 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 @@ -7,19 +7,19 @@ package io.element.android.libraries.sessionstorage.test -import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.sessionstorage.api.LoginType import io.element.android.libraries.sessionstorage.api.SessionData fun aSessionData( - sessionId: SessionId = SessionId("@alice:server.org"), + sessionId: String = "@alice:server.org", + deviceId: String = "aDeviceId", isTokenValid: Boolean = false, sessionPath: String = "/a/path/to/a/session", cachePath: String = "/a/path/to/a/cache", ): SessionData { return SessionData( - userId = sessionId.value, - deviceId = "aDeviceId", + userId = sessionId, + deviceId = deviceId, accessToken = "anAccessToken", refreshToken = "aRefreshToken", homeserverUrl = "aHomeserverUrl", From 85ff062c73739bff8098683e6987848ed7d70f7f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Sep 2024 20:34:39 +0200 Subject: [PATCH 49/56] Add unit test on SessionPathsProvider --- libraries/matrix/impl/build.gradle.kts | 2 + .../impl/util/SessionPathsProviderTest.kt | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt diff --git a/libraries/matrix/impl/build.gradle.kts b/libraries/matrix/impl/build.gradle.kts index 5d386169ad..c13189b198 100644 --- a/libraries/matrix/impl/build.gradle.kts +++ b/libraries/matrix/impl/build.gradle.kts @@ -47,6 +47,8 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.robolectric) testImplementation(projects.libraries.matrix.test) + testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.services.analytics.test) testImplementation(projects.services.toolbox.test) testImplementation(projects.tests.testutils) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.kt new file mode 100644 index 0000000000..f530fc04cc --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/util/SessionPathsProviderTest.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.util + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore +import io.element.android.libraries.sessionstorage.test.aSessionData +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class SessionPathsProviderTest { + @Test + fun `if session is not found, provides returns null`() = runTest { + val sut = SessionPathsProvider(InMemorySessionStore()) + val result = sut.provides(A_SESSION_ID) + assertThat(result).isNull() + } + + @Test + fun `if session is found, provides returns the data`() = runTest { + val store = InMemorySessionStore() + val sut = SessionPathsProvider(store) + store.storeData( + aSessionData( + sessionPath = "/a/path/to/a/session", + cachePath = "/a/path/to/a/cache", + ) + ) + val result = sut.provides(A_SESSION_ID)!! + assertThat(result.fileDirectory.absolutePath).isEqualTo("/a/path/to/a/session") + assertThat(result.cacheDirectory.absolutePath).isEqualTo("/a/path/to/a/cache") + } +} From e9a898ff82ab0bd049625b013ecad54670ab384f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:07:57 +0200 Subject: [PATCH 50/56] Cleanup --- .../impl/migrations/AppMigration05Test.kt | 4 +- .../impl/migrations/AppMigration06Test.kt | 4 +- features/signedout/impl/build.gradle.kts | 1 + .../signedout/impl/SignedOutPresenterTest.kt | 1 + .../timeline/MatrixTimelineDiffProcessor.kt | 6 +-- .../QrLoginProgressExtensionsKtTest.kt | 2 - .../impl/encryption/BackupStateMapperTest.kt | 15 +++--- .../encryption/BackupUploadStateMapperTest.kt | 12 +++-- .../EnableRecoveryProgressMapperTest.kt | 13 ++--- .../encryption/RecoveryStateMapperTest.kt | 9 ++-- .../fixtures/factories/RoomDescription.kt | 26 ++++++++++ .../impl/fixtures/factories/RoomHero.kt | 22 ++++++++ .../RoomInfo.kt} | 2 +- .../RoomMember.kt} | 2 +- .../fixtures/factories/RoomPowerLevels.kt | 34 ++++++++++++ .../impl/fixtures/factories/RoomPreview.kt | 35 +++++++++++++ .../fixtures/factories/SearchUsersResults.kt | 20 +++++++ .../matrix/impl/fixtures/factories/Session.kt | 28 ++++++++++ .../impl/fixtures/factories/UserProfile.kt | 21 ++++++++ .../impl/fixtures/{ => fakes}/FakeRustRoom.kt | 2 +- .../{ => fakes}/FakeRustRoomListItem.kt | 3 +- .../FakeRustRoomMembersIterator.kt | 2 +- .../fixtures/fakes/FakeRustTimelineDiff.kt | 30 +++++++++++ .../fixtures/fakes/FakeRustTimelineItem.kt | 20 +++++++ .../matrix/impl/mapper/SessionKtTest.kt | 16 +----- .../matrix/impl/poll/PollKindKtTest.kt | 1 - .../impl/room/MatrixRoomInfoMapperTest.kt | 11 ++-- .../impl/room/MessageEventTypeKtTest.kt | 3 +- .../matrix/impl/room/RoomInfoExtTest.kt | 21 +++----- .../matrix/impl/room/StateEventTypeTest.kt | 3 +- .../room/member/RoomMemberListFetcherTest.kt | 6 +-- .../powerlevels/RoomPowerLevelsMapperTest.kt | 4 +- .../room/preview/RoomPreviewMapperTest.kt | 25 +-------- .../RoomDescriptionMapperTest.kt | 15 +----- .../roomlist/RoomSummaryListProcessorTest.kt | 2 +- .../MatrixTimelineDiffProcessorTest.kt | 52 +++++-------------- .../impl/timeline/postprocessor/Fixtures.kt | 1 - .../RoomBeginningPostProcessorTest.kt | 1 - .../impl/usersearch/UserProfileMapperTest.kt | 4 +- .../usersearch/UserSearchResultMapperTest.kt | 14 ++--- .../DefaultFirebaseNewTokenHandlerTest.kt | 10 ++-- 41 files changed, 327 insertions(+), 176 deletions(-) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{RustRoomInfo.kt => factories/RoomInfo.kt} (97%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{RustRoomMember.kt => factories/RoomMember.kt} (93%) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoom.kt (94%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoomListItem.kt (85%) rename libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/{ => fakes}/FakeRustRoomMembersIterator.kt (92%) create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt create mode 100644 libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt diff --git a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt index 394c4a34b3..850674cde7 100644 --- a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt +++ b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration05Test.kt @@ -21,7 +21,7 @@ class AppMigration05Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "", ) ) @@ -37,7 +37,7 @@ class AppMigration05Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "/a/path/existing", ) ) diff --git a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt index 6e1b9a237d..f60a3af5ad 100644 --- a/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt +++ b/features/migration/impl/src/test/kotlin/io/element/android/features/migration/impl/migrations/AppMigration06Test.kt @@ -21,7 +21,7 @@ class AppMigration06Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, sessionPath = "/a/path/to/a/session/AN_ID", cachePath = "", ) @@ -38,7 +38,7 @@ class AppMigration06Test { val sessionStore = InMemorySessionStore().apply { updateData( aSessionData( - sessionId = A_SESSION_ID, + sessionId = A_SESSION_ID.value, cachePath = "/a/path/existing", ) ) diff --git a/features/signedout/impl/build.gradle.kts b/features/signedout/impl/build.gradle.kts index 35ad8ecb16..8d8b3f518c 100644 --- a/features/signedout/impl/build.gradle.kts +++ b/features/signedout/impl/build.gradle.kts @@ -37,5 +37,6 @@ dependencies { testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.sessionStorage.implMemory) + testImplementation(projects.libraries.sessionStorage.test) testImplementation(projects.tests.testutils) } diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index 8945020da3..a5390c153e 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.core.aBuildMeta 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.WarmUpRule import kotlinx.coroutines.test.runTest import org.junit.Rule diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt index 3523823d5e..a48817efa5 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessor.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiffInterface +import org.matrix.rustcomponents.sdk.TimelineDiff import org.matrix.rustcomponents.sdk.TimelineItem import timber.log.Timber @@ -36,7 +36,7 @@ internal class MatrixTimelineDiffProcessor( } } - suspend fun postDiffs(diffs: List) { + suspend fun postDiffs(diffs: List) { updateTimelineItems { Timber.v("Update timeline items from postDiffs (with ${diffs.size} items) on ${Thread.currentThread()}") diffs.forEach { diff -> @@ -52,7 +52,7 @@ internal class MatrixTimelineDiffProcessor( timelineItems.value = mutableTimelineItems } - private fun MutableList.applyDiff(diff: TimelineDiffInterface) { + private fun MutableList.applyDiff(diff: TimelineDiff) { when (diff.change()) { TimelineChange.APPEND -> { val items = diff.append()?.map { it.asMatrixTimelineItem() } ?: return diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt index 0de3d15e57..172b415e98 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/auth/qrlogin/QrLoginProgressExtensionsKtTest.kt @@ -25,5 +25,3 @@ class QrLoginProgressExtensionsKtTest { .isEqualTo(QrCodeLoginStep.Finished) } } - - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt index fc804b0978..f529aacbcb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupStateMapperTest.kt @@ -15,12 +15,13 @@ import org.matrix.rustcomponents.sdk.BackupState as RustBackupState class BackupStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(BackupStateMapper().map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) - assertThat(BackupStateMapper().map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) - assertThat(BackupStateMapper().map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) - assertThat(BackupStateMapper().map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) - assertThat(BackupStateMapper().map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) - assertThat(BackupStateMapper().map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) - assertThat(BackupStateMapper().map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) + val sut = BackupStateMapper() + assertThat(sut.map(RustBackupState.UNKNOWN)).isEqualTo(BackupState.UNKNOWN) + assertThat(sut.map(RustBackupState.CREATING)).isEqualTo(BackupState.CREATING) + assertThat(sut.map(RustBackupState.ENABLING)).isEqualTo(BackupState.ENABLING) + assertThat(sut.map(RustBackupState.RESUMING)).isEqualTo(BackupState.RESUMING) + assertThat(sut.map(RustBackupState.ENABLED)).isEqualTo(BackupState.ENABLED) + assertThat(sut.map(RustBackupState.DOWNLOADING)).isEqualTo(BackupState.DOWNLOADING) + assertThat(sut.map(RustBackupState.DISABLING)).isEqualTo(BackupState.DISABLING) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt index 7c1ad1d7c5..6148cd6971 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/BackupUploadStateMapperTest.kt @@ -15,19 +15,21 @@ import org.matrix.rustcomponents.sdk.BackupUploadState as RustBackupUploadState class BackupUploadStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Waiting)) + val sut = BackupUploadStateMapper() + assertThat(sut.map(RustBackupUploadState.Waiting)) .isEqualTo(BackupUploadState.Waiting) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Error)) + assertThat(sut.map(RustBackupUploadState.Error)) .isEqualTo(BackupUploadState.Error) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Done)) + assertThat(sut.map(RustBackupUploadState.Done)) .isEqualTo(BackupUploadState.Done) - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) + assertThat(sut.map(RustBackupUploadState.Uploading(1.toUInt(), 2.toUInt()))) .isEqualTo(BackupUploadState.Uploading(1, 2)) } @Test fun `Ensure that full uploading is mapper to Done`() { - assertThat(BackupUploadStateMapper().map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) + val sut = BackupUploadStateMapper() + assertThat(sut.map(RustBackupUploadState.Uploading(2.toUInt(), 2.toUInt()))) .isEqualTo(BackupUploadState.Done) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt index 191a7f3964..fb39ff2d38 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/EnableRecoveryProgressMapperTest.kt @@ -15,17 +15,18 @@ import org.matrix.rustcomponents.sdk.EnableRecoveryProgress as RustEnableRecover class EnableRecoveryProgressMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingRecoveryKey)) + val sut = EnableRecoveryProgressMapper() + assertThat(sut.map(RustEnableRecoveryProgress.CreatingRecoveryKey)) .isEqualTo(EnableRecoveryProgress.CreatingRecoveryKey) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.CreatingBackup)) + assertThat(sut.map(RustEnableRecoveryProgress.CreatingBackup)) .isEqualTo(EnableRecoveryProgress.CreatingBackup) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Starting)) + assertThat(sut.map(RustEnableRecoveryProgress.Starting)) .isEqualTo(EnableRecoveryProgress.Starting) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) + assertThat(sut.map(RustEnableRecoveryProgress.BackingUp(1.toUInt(), 2.toUInt()))) .isEqualTo(EnableRecoveryProgress.BackingUp(1, 2)) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.RoomKeyUploadError)) + assertThat(sut.map(RustEnableRecoveryProgress.RoomKeyUploadError)) .isEqualTo(EnableRecoveryProgress.RoomKeyUploadError) - assertThat(EnableRecoveryProgressMapper().map(RustEnableRecoveryProgress.Done("recoveryKey"))) + assertThat(sut.map(RustEnableRecoveryProgress.Done("recoveryKey"))) .isEqualTo(EnableRecoveryProgress.Done("recoveryKey")) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt index 9d7c2d0c04..b3c93af7ef 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/encryption/RecoveryStateMapperTest.kt @@ -15,9 +15,10 @@ import org.matrix.rustcomponents.sdk.RecoveryState as RustRecoveryState class RecoveryStateMapperTest { @Test fun `Ensure that mapping is correct`() { - assertThat(RecoveryStateMapper().map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) - assertThat(RecoveryStateMapper().map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) - assertThat(RecoveryStateMapper().map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) - assertThat(RecoveryStateMapper().map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) + val sut = RecoveryStateMapper() + assertThat(sut.map(RustRecoveryState.UNKNOWN)).isEqualTo(RecoveryState.UNKNOWN) + assertThat(sut.map(RustRecoveryState.ENABLED)).isEqualTo(RecoveryState.ENABLED) + assertThat(sut.map(RustRecoveryState.DISABLED)).isEqualTo(RecoveryState.DISABLED) + assertThat(sut.map(RustRecoveryState.INCOMPLETE)).isEqualTo(RecoveryState.INCOMPLETE) } } 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 new file mode 100644 index 0000000000..d80b3d3723 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomDescription.kt @@ -0,0 +1,26 @@ +/* + * 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_ROOM_ALIAS +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 { + 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 + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt new file mode 100644 index 0000000000..0eac725c2e --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomHero.kt @@ -0,0 +1,22 @@ +/* + * 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.api.core.UserId +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.RoomHero + +internal fun aRustRoomHero( + userId: UserId = A_USER_ID, +): RoomHero { + return RoomHero( + userId = userId.value, + displayName = "displayName", + avatarUrl = "avatarUrl", + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt similarity index 97% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt index b78780ee23..e7e3ff219f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomInfo.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomInfo.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.test.A_ROOM_ID diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt similarity index 93% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt index 918ae1fe12..7aebed99ea 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/RustRoomMember.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomMember.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.factories import io.element.android.libraries.matrix.api.core.UserId import org.matrix.rustcomponents.sdk.MembershipState diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt new file mode 100644 index 0000000000..adfb65c19a --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPowerLevels.kt @@ -0,0 +1,34 @@ +/* + * 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.RoomPowerLevels + +internal fun aRustRoomPowerLevels( + ban: Long, + invite: Long, + kick: Long, + redact: Long, + eventsDefault: Long, + stateDefault: Long, + usersDefault: Long, + roomName: Long, + roomAvatar: Long, + roomTopic: Long, +) = RoomPowerLevels( + ban = ban, + invite = invite, + kick = kick, + redact = redact, + eventsDefault = eventsDefault, + stateDefault = stateDefault, + usersDefault = usersDefault, + roomName = roomName, + roomAvatar = roomAvatar, + roomTopic = roomTopic, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt new file mode 100644 index 0000000000..54abeb90b8 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/RoomPreview.kt @@ -0,0 +1,35 @@ +/* + * 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_ROOM_ALIAS +import io.element.android.libraries.matrix.test.A_ROOM_ID +import org.matrix.rustcomponents.sdk.RoomPreview + +internal fun aRustRoomPreview( + canonicalAlias: String? = A_ROOM_ALIAS.value, + isJoined: Boolean = true, + isInvited: Boolean = true, + isPublic: Boolean = true, + canKnock: Boolean = true, +): RoomPreview { + return RoomPreview( + roomId = A_ROOM_ID.value, + canonicalAlias = canonicalAlias, + name = "name", + topic = "topic", + avatarUrl = "avatarUrl", + numJoinedMembers = 1u, + roomType = null, + isHistoryWorldReadable = true, + isJoined = isJoined, + isInvited = isInvited, + isPublic = isPublic, + canKnock = canKnock, + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt new file mode 100644 index 0000000000..d051a1fb2d --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.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.factories + +import org.matrix.rustcomponents.sdk.SearchUsersResults +import org.matrix.rustcomponents.sdk.UserProfile + +internal fun aRustSearchUsersResults( + results: List, + limited: Boolean, +) = SearchUsersResults( + results = results, + limited = limited, +) + 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 new file mode 100644 index 0000000000..64d1667157 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/Session.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.fixtures.factories + +import io.element.android.libraries.matrix.test.A_DEVICE_ID +import io.element.android.libraries.matrix.test.A_HOMESERVER_URL +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.Session +import org.matrix.rustcomponents.sdk.SlidingSyncVersion + +internal fun aRustSession( + proxy: SlidingSyncVersion = SlidingSyncVersion.None +): Session { + return Session( + accessToken = "accessToken", + refreshToken = "refreshToken", + userId = A_USER_ID.value, + deviceId = A_DEVICE_ID.value, + homeserverUrl = A_HOMESERVER_URL, + oidcData = null, + slidingSyncVersion = proxy, + ) +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.kt new file mode 100644 index 0000000000..f6444d1376 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/UserProfile.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.factories + +import io.element.android.libraries.matrix.test.A_USER_ID +import org.matrix.rustcomponents.sdk.UserProfile + +fun aRustUserProfile( + userId: String = A_USER_ID.value, + displayName: String = "displayName", + avatarUrl: String = "avatarUrl", +) = UserProfile( + userId = userId, + displayName = displayName, + avatarUrl = avatarUrl, +) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt similarity index 94% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt index a9321bf347..f066f37e9b 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoom.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoom.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.test.A_ROOM_ID diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt similarity index 85% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt index 1b9adee435..6d20221d88 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomListItem.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomListItem.kt @@ -5,9 +5,10 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import org.matrix.rustcomponents.sdk.EventTimelineItem import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomInfo diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt similarity index 92% rename from libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt rename to libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt index e5a0646303..6d44ccbc75 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/FakeRustRoomMembersIterator.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustRoomMembersIterator.kt @@ -5,7 +5,7 @@ * Please see LICENSE in the repository root for full details. */ -package io.element.android.libraries.matrix.impl.fixtures +package io.element.android.libraries.matrix.impl.fixtures.fakes import org.matrix.rustcomponents.sdk.NoPointer import org.matrix.rustcomponents.sdk.RoomMember diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.kt new file mode 100644 index 0000000000..f4fe5e15d9 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineDiff.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.fixtures.fakes + +import org.matrix.rustcomponents.sdk.InsertData +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.SetData +import org.matrix.rustcomponents.sdk.TimelineChange +import org.matrix.rustcomponents.sdk.TimelineDiff +import org.matrix.rustcomponents.sdk.TimelineItem + +class FakeRustTimelineDiff( + private val change: TimelineChange, + private val item: TimelineItem? = FakeRustTimelineItem() +) : TimelineDiff(NoPointer) { + override fun change() = change + override fun append(): List? = item?.let { listOf(it) } + override fun insert(): InsertData? = item?.let { InsertData(1u, it) } + override fun pushBack(): TimelineItem? = item + override fun pushFront(): TimelineItem? = item + override fun remove(): UInt? = 1u + override fun reset(): List? = item?.let { listOf(it) } + override fun set(): SetData? = item?.let { SetData(1u, it) } + override fun truncate(): UInt? = 1u +} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.kt new file mode 100644 index 0000000000..c20698fe62 --- /dev/null +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/fakes/FakeRustTimelineItem.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.EventTimelineItem +import org.matrix.rustcomponents.sdk.NoPointer +import org.matrix.rustcomponents.sdk.TimelineItem +import org.matrix.rustcomponents.sdk.VirtualTimelineItem + +class FakeRustTimelineItem : TimelineItem(NoPointer) { + override fun asEvent(): EventTimelineItem? = null + override fun asVirtual(): VirtualTimelineItem? = null + override fun fmtDebug(): String = "fmtDebug" + override fun uniqueId(): String = "uniqueId" +} 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 aac34dfdab..9e6d87957c 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.impl.fixtures.factories.aRustSession import io.element.android.libraries.matrix.impl.paths.SessionPaths import io.element.android.libraries.matrix.test.A_DEVICE_ID import io.element.android.libraries.matrix.test.A_HOMESERVER_URL @@ -16,7 +17,6 @@ import io.element.android.libraries.matrix.test.A_SECRET import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.sessionstorage.api.LoginType import org.junit.Test -import org.matrix.rustcomponents.sdk.Session import org.matrix.rustcomponents.sdk.SlidingSyncVersion import java.io.File @@ -82,17 +82,3 @@ class SessionKtTest { assertThat(result.slidingSyncProxy).isEqualTo("proxyUrl") } } - -internal fun aRustSession( - proxy: SlidingSyncVersion = SlidingSyncVersion.None -): Session { - return Session( - accessToken = "accessToken", - refreshToken = "refreshToken", - userId = A_USER_ID.value, - deviceId = A_DEVICE_ID.value, - homeserverUrl = A_HOMESERVER_URL, - oidcData = null, - slidingSyncVersion = proxy, - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt index 97f049bcb7..4be515530c 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/poll/PollKindKtTest.kt @@ -12,7 +12,6 @@ import io.element.android.libraries.matrix.api.poll.PollKind import org.junit.Test import org.matrix.rustcomponents.sdk.PollKind as RustPollKind - class PollKindKtTest { @Test fun `map should return Disclosed when RustPollKind is Disclosed`() { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt index ce04469ff8..c9e80f493d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapperTest.kt @@ -15,8 +15,9 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.MatrixRoomInfo import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.impl.room.member.aRustRoomMember -import io.element.android.libraries.matrix.impl.roomlist.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ALIAS @@ -52,7 +53,7 @@ class MatrixRoomInfoMapperTest { alternativeAliases = listOf(A_ROOM_ALIAS.value), membership = Membership.JOINED, inviter = aRustRoomMember(A_USER_ID), - heroes = listOf(aRoomHero()), + heroes = listOf(aRustRoomHero()), activeMembersCount = 2uL, invitedMembersCount = 3uL, joinedMembersCount = 4uL, @@ -67,7 +68,7 @@ class MatrixRoomInfoMapperTest { numUnreadNotifications = 13uL, numUnreadMentions = 14uL, pinnedEventIds = listOf(AN_EVENT_ID.value), - roomCreator = A_USER_ID.value, + roomCreator = A_USER_ID, ) ) ).isEqualTo( @@ -127,7 +128,7 @@ class MatrixRoomInfoMapperTest { alternativeAliases = emptyList(), membership = Membership.INVITED, inviter = null, - heroes = listOf(aRoomHero()), + heroes = listOf(aRustRoomHero()), activeMembersCount = 2uL, invitedMembersCount = 3uL, joinedMembersCount = 4uL, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt index 847c41e89a..3c439d28b0 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/MessageEventTypeKtTest.kt @@ -8,9 +8,8 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat -import org.junit.Test - import io.element.android.libraries.matrix.api.room.MessageEventType +import org.junit.Test import org.matrix.rustcomponents.sdk.MessageLikeEventType class MessageEventTypeKtTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index 7d671d0972..d65f042019 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -10,10 +10,10 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser -import io.element.android.libraries.matrix.impl.fixtures.aRustRoomInfo +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomHero class RoomInfoExtTest { @Test @@ -21,7 +21,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 2uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEqualTo( listOf( @@ -39,7 +39,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 2uL, - heroes = listOf(aRoomHero(), aRoomHero()) + heroes = listOf(aRustRoomHero(), aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } @@ -49,7 +49,7 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = false, activeMembersCount = 2uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } @@ -59,18 +59,9 @@ class RoomInfoExtTest { val result = aRustRoomInfo( isDirect = true, activeMembersCount = 3uL, - heroes = listOf(aRoomHero()) + heroes = listOf(aRustRoomHero()) ).elementHeroes() assertThat(result).isEmpty() } } -internal fun aRoomHero( - userId: UserId = A_USER_ID, -): RoomHero { - return RoomHero( - userId = userId.value, - displayName = "displayName", - avatarUrl = "avatarUrl", - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt index 3772ae780d..1900575bbf 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/StateEventTypeTest.kt @@ -8,9 +8,8 @@ package io.element.android.libraries.matrix.impl.room import com.google.common.truth.Truth.assertThat -import org.junit.Test - import io.element.android.libraries.matrix.api.room.StateEventType +import org.junit.Test import org.matrix.rustcomponents.sdk.StateEventType as RustStateEventType class StateEventTypeTest { diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index dc8489e48f..549f7e5ac2 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -11,9 +11,9 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers -import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoom -import io.element.android.libraries.matrix.impl.fixtures.FakeRustRoomMembersIterator -import io.element.android.libraries.matrix.impl.fixtures.aRustRoomMember +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomMembersIterator +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt index 2a8a89004d..20cbdc5deb 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/powerlevels/RoomPowerLevelsMapperTest.kt @@ -9,15 +9,15 @@ package io.element.android.libraries.matrix.impl.room.powerlevels import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPowerLevels import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomPowerLevels as RustRoomPowerLevels class RoomPowerLevelsMapperTest { @Test fun `test that mapping of RoomPowerLevels is correct`() { assertThat( RoomPowerLevelsMapper.map( - RustRoomPowerLevels( + aRustRoomPowerLevels( ban = 1, invite = 2, kick = 3, diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt index 3e0fea4bdc..7d7890198e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/preview/RoomPreviewMapperTest.kt @@ -10,10 +10,10 @@ package io.element.android.libraries.matrix.impl.room.preview import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.RoomType import io.element.android.libraries.matrix.api.room.preview.RoomPreview +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomPreview import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.RoomPreview as RustRoomPreview class RoomPreviewMapperTest { @Test @@ -71,26 +71,3 @@ class RoomPreviewMapperTest { ) } } - -internal fun aRustRoomPreview( - canonicalAlias: String? = A_ROOM_ALIAS.value, - isJoined: Boolean = true, - isInvited: Boolean = true, - isPublic: Boolean = true, - canKnock: Boolean = true, -): RustRoomPreview { - return RustRoomPreview( - roomId = A_ROOM_ID.value, - canonicalAlias = canonicalAlias, - name = "name", - topic = "topic", - avatarUrl = "avatarUrl", - numJoinedMembers = 1u, - roomType = null, - isHistoryWorldReadable = true, - isJoined = isJoined, - isInvited = isInvited, - isPublic = isPublic, - canKnock = canKnock, - ) -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt index 307cc33b54..808b15dd1f 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomdirectory/RoomDescriptionMapperTest.kt @@ -9,12 +9,12 @@ package io.element.android.libraries.matrix.impl.roomdirectory import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.roomdirectory.RoomDescription +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomDescription import io.element.android.libraries.matrix.test.A_ROOM_ALIAS import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.roomdirectory.aRoomDescription import org.junit.Test import org.matrix.rustcomponents.sdk.PublicRoomJoinRule -import org.matrix.rustcomponents.sdk.RoomDescription as RustRoomDescription class RoomDescriptionMapperTest { @Test @@ -45,16 +45,3 @@ class RoomDescriptionMapperTest { assertThat(null.map()).isEqualTo(RoomDescription.JoinRule.UNKNOWN) } } - -internal fun aRustRoomDescription(): RustRoomDescription { - return RustRoomDescription( - roomId = A_ROOM_ID.value, - name = "name", - topic = "topic", - alias = A_ROOM_ALIAS.value, - avatarUrl = "avatarUrl", - joinRule = PublicRoomJoinRule.PUBLIC, - isWorldReadable = true, - joinedMembers = 2u - ) -} 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 d4b347af44..d6ed69706c 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 @@ -10,7 +10,7 @@ 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.FakeRustRoomListItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomListItem 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 diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt index 84ce6e61f9..d442d004d6 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/MatrixTimelineDiffProcessorTest.kt @@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustTimelineDiff import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper @@ -19,29 +20,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.matrix.rustcomponents.sdk.EventTimelineItem -import org.matrix.rustcomponents.sdk.InsertData -import org.matrix.rustcomponents.sdk.NoPointer -import org.matrix.rustcomponents.sdk.SetData import org.matrix.rustcomponents.sdk.TimelineChange -import org.matrix.rustcomponents.sdk.TimelineDiffInterface -import org.matrix.rustcomponents.sdk.TimelineItem -import org.matrix.rustcomponents.sdk.VirtualTimelineItem - -open class FakeTimelineDiff( - private val change: TimelineChange, - private val item: TimelineItem? = FakeTimelineItem() -) : TimelineDiffInterface { - override fun change() = change - override fun append(): List? = item?.let { listOf(it) } - override fun insert(): InsertData? = item?.let { InsertData(1u, it) } - override fun pushBack(): TimelineItem? = item - override fun pushFront(): TimelineItem? = item - override fun remove(): UInt? = 1u - override fun reset(): List? = item?.let { listOf(it) } - override fun set(): SetData? = item?.let { SetData(1u, it) } - override fun truncate(): UInt? = 1u -} class MatrixTimelineDiffProcessorTest { private val timelineItems = MutableStateFlow>(emptyList()) @@ -53,7 +32,7 @@ class MatrixTimelineDiffProcessorTest { fun `Append adds new entries at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.APPEND))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.APPEND))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -65,7 +44,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushBack adds a new entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_BACK))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_BACK))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -77,7 +56,7 @@ class MatrixTimelineDiffProcessorTest { fun `PushFront inserts a new entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.PUSH_FRONT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.PUSH_FRONT))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, @@ -89,7 +68,7 @@ class MatrixTimelineDiffProcessorTest { fun `Set replaces an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.SET))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.SET))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -101,7 +80,7 @@ class MatrixTimelineDiffProcessorTest { fun `Insert inserts a new entry at the provided index`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.INSERT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.INSERT))) assertThat(timelineItems.value.count()).isEqualTo(3) assertThat(timelineItems.value).containsExactly( anEvent, @@ -114,7 +93,7 @@ class MatrixTimelineDiffProcessorTest { fun `Remove removes an entry at some index`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.REMOVE))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.REMOVE))) assertThat(timelineItems.value.count()).isEqualTo(2) assertThat(timelineItems.value).containsExactly( anEvent, @@ -126,7 +105,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopBack removes an entry at the end of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_BACK))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_BACK))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -137,7 +116,7 @@ class MatrixTimelineDiffProcessorTest { fun `PopFront removes an entry at the start of the list`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.POP_FRONT))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.POP_FRONT))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent2, @@ -148,7 +127,7 @@ class MatrixTimelineDiffProcessorTest { fun `Clear removes all the entries`() = runTest { timelineItems.value = listOf(anEvent, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.CLEAR))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.CLEAR))) assertThat(timelineItems.value).isEmpty() } @@ -156,7 +135,7 @@ class MatrixTimelineDiffProcessorTest { fun `Truncate removes all entries after the provided length`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.TRUNCATE))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.TRUNCATE))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( anEvent, @@ -167,7 +146,7 @@ class MatrixTimelineDiffProcessorTest { fun `Reset removes all entries and add the provided ones`() = runTest { timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2) val processor = createProcessor() - processor.postDiffs(listOf(FakeTimelineDiff(change = TimelineChange.RESET))) + processor.postDiffs(listOf(FakeRustTimelineDiff(change = TimelineChange.RESET))) assertThat(timelineItems.value.count()).isEqualTo(1) assertThat(timelineItems.value).containsExactly( MatrixTimelineItem.Other, @@ -190,10 +169,3 @@ class MatrixTimelineDiffProcessorTest { ) } } - -class FakeTimelineItem : TimelineItem(NoPointer) { - override fun asEvent(): EventTimelineItem? = null - override fun asVirtual(): VirtualTimelineItem? = null - override fun fmtDebug(): String = "fmtDebug" - override fun uniqueId(): String = "uniqueId" -} diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt index 16acfd718f..cc295d2517 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/Fixtures.kt @@ -43,4 +43,3 @@ internal val dayEvent = MatrixTimelineItem.Virtual( uniqueId = UniqueId("day"), virtual = VirtualTimelineItem.DayDivider(0), ) - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt index 41d175b348..f7eadd0d47 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt @@ -13,7 +13,6 @@ import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test class RoomBeginningPostProcessorTest { - @Test fun `processor returns empty list when empty list is provided`() { val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt index 0564186a78..f8bb7a0e0e 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserProfileMapperTest.kt @@ -9,14 +9,14 @@ package io.element.android.libraries.matrix.impl.usersearch import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile import io.element.android.libraries.matrix.test.A_USER_ID import org.junit.Test -import org.matrix.rustcomponents.sdk.UserProfile class UserProfileMapperTest { @Test fun map() { - assertThat(UserProfileMapper.map(UserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) + assertThat(UserProfileMapper.map(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl"))) .isEqualTo(MatrixUser(A_USER_ID, "displayName", "avatarUrl")) } } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt index 17ce3836ca..068515e255 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/usersearch/UserSearchResultMapperTest.kt @@ -10,19 +10,19 @@ package io.element.android.libraries.matrix.impl.usersearch import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchUsersResults +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile import io.element.android.libraries.matrix.test.A_USER_ID import kotlinx.collections.immutable.toImmutableList import org.junit.Test -import org.matrix.rustcomponents.sdk.SearchUsersResults -import org.matrix.rustcomponents.sdk.UserProfile class UserSearchResultMapperTest { @Test fun `map limited list`() { assertThat( UserSearchResultMapper.map( - SearchUsersResults( - results = listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + aRustSearchUsersResults( + results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")), limited = true, ) ) @@ -39,9 +39,9 @@ class UserSearchResultMapperTest { fun `map not limited list`() { assertThat( UserSearchResultMapper.map( - SearchUsersResults( - listOf(UserProfile(A_USER_ID.value, "displayName", "avatarUrl")), - false, + aRustSearchUsersResults( + results = listOf(aRustUserProfile(A_USER_ID.value, "displayName", "avatarUrl")), + limited = false, ) ) ) diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt index 2da1e8554d..668eeebf98 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/DefaultFirebaseNewTokenHandlerTest.kt @@ -51,9 +51,9 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) - storeData(aSessionData(A_USER_ID_2)) - storeData(aSessionData(A_USER_ID_3)) + storeData(aSessionData(A_USER_ID.value)) + storeData(aSessionData(A_USER_ID_2.value)) + storeData(aSessionData(A_USER_ID_3.value)) }, matrixClientProvider = FakeMatrixClientProvider { sessionId -> when (sessionId) { @@ -90,7 +90,7 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) + storeData(aSessionData(A_USER_ID.value)) }, matrixClientProvider = FakeMatrixClientProvider { Result.failure(IllegalStateException()) @@ -114,7 +114,7 @@ class DefaultFirebaseNewTokenHandlerTest { val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult) val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler( sessionStore = InMemoryMultiSessionsStore().apply { - storeData(aSessionData(A_USER_ID)) + storeData(aSessionData(A_USER_ID.value)) }, matrixClientProvider = FakeMatrixClientProvider { Result.success(aMatrixClient1) From 4a4a8073fa33a00e923467f0c72382b02a9955e6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:41:28 +0200 Subject: [PATCH 51/56] Cleanup --- .../matrix/impl/fixtures/factories/SearchUsersResults.kt | 1 - .../android/libraries/matrix/impl/room/RoomInfoExtTest.kt | 1 - .../matrix/impl/room/member/RoomMemberListFetcherTest.kt | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt index d051a1fb2d..f8397d066d 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/fixtures/factories/SearchUsersResults.kt @@ -17,4 +17,3 @@ internal fun aRustSearchUsersResults( results = results, limited = limited, ) - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt index d65f042019..8cf3134825 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/RoomInfoExtTest.kt @@ -64,4 +64,3 @@ class RoomInfoExtTest { assertThat(result).isEmpty() } } - diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt index 549f7e5ac2..a65995fc86 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/room/member/RoomMemberListFetcherTest.kt @@ -11,9 +11,9 @@ import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState import io.element.android.libraries.matrix.api.room.roomMembers +import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoom import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustRoomMembersIterator -import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomMember import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.CACHE_AND_SERVER import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher.Source.SERVER From 2d9b0bbe19eb12094279d28addbfa6e235a35c74 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 Sep 2024 18:50:54 +0200 Subject: [PATCH 52/56] Adapt Konsist test for Fake Rust classes. --- .../element/android/tests/konsist/KonsistClassNameTest.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt index 7ec2784c70..797f13dbe8 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistClassNameTest.kt @@ -68,11 +68,12 @@ class KonsistClassNameTest { .withoutName( "FakeFileSystem", "FakeImageLoader", - "FakeRustRoom", ) .assertTrue { - val interfaceName = it.name.replace("Fake", "") - it.name.startsWith("Fake") && + val interfaceName = it.name + .replace("FakeRust", "") + .replace("Fake", "") + (it.name.startsWith("Fake") || it.name.startsWith("FakeRust")) && it.parents().any { parent -> parent.name.replace(".", "") == interfaceName } } } From 730aa95da6992eaaa2530845e9572ccbebd7a548 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 20:35:57 +0200 Subject: [PATCH 53/56] Rust sdk : update to 0.2.47 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14d38d3a2c..f33fa0275a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -162,7 +162,7 @@ jsoup = "org.jsoup:jsoup:1.18.1" appyx_core = { module = "com.bumble.appyx:core", version.ref = "appyx" } molecule-runtime = "app.cash.molecule:molecule-runtime:2.0.0" timber = "com.jakewharton.timber:timber:5.0.1" -matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.46" +matrix_sdk = "org.matrix.rustcomponents:sdk-android:0.2.47" matrix_richtexteditor = { module = "io.element.android:wysiwyg", version.ref = "wysiwyg" } matrix_richtexteditor_compose = { module = "io.element.android:wysiwyg-compose", version.ref = "wysiwyg" } sqldelight-driver-android = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" } From b364cee500de37a416d4027e61d5d0102dbd9326 Mon Sep 17 00:00:00 2001 From: ganfra Date: Wed, 18 Sep 2024 21:07:39 +0200 Subject: [PATCH 54/56] Room list : debounce subscribe to visible rooms. --- .../android/features/roomlist/impl/RoomListPresenter.kt | 8 ++++++-- .../libraries/matrix/impl/roomlist/RustRoomListService.kt | 6 +----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index 2983b6b695..bd65b2634d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -61,7 +61,7 @@ import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first @@ -73,6 +73,7 @@ import kotlinx.coroutines.launch import javax.inject.Inject private const val EXTENDED_RANGE_SIZE = 40 +private const val SUBSCRIBE_TO_VISIBLE_ROOMS_DEBOUNCE_IN_MILLIS = 300L class RoomListPresenter @Inject constructor( private val client: MatrixClient, @@ -301,7 +302,10 @@ class RoomListPresenter @Inject constructor( private var currentUpdateVisibleRangeJob: Job? = null private fun CoroutineScope.updateVisibleRange(range: IntRange) { currentUpdateVisibleRangeJob?.cancel() - currentUpdateVisibleRangeJob = launch(SupervisorJob()) { + currentUpdateVisibleRangeJob = launch { + // Debounce the subscription to avoid subscribing to too many rooms + delay(SUBSCRIBE_TO_VISIBLE_ROOMS_DEBOUNCE_IN_MILLIS) + if (range.isEmpty()) return@launch val currentRoomList = roomListDataSource.allRooms.first() // Use extended range to 'prefetch' the next rooms info 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 b203ec958f..ee0be05e4b 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 @@ -53,11 +53,7 @@ internal class RustRoomListService( } override suspend fun subscribeToVisibleRooms(roomIds: List) { - val toSubscribe = roomIds.filterNot { roomSyncSubscriber.isSubscribedTo(it) } - if (toSubscribe.isNotEmpty()) { - Timber.d("Subscribe to ${toSubscribe.size} rooms: $toSubscribe") - roomSyncSubscriber.batchSubscribe(toSubscribe) - } + roomSyncSubscriber.batchSubscribe(roomIds) } override val allRooms: DynamicRoomList = roomListFactory.createRoomList( From 4b2ea110371974fcd62f0768ac6502370bd8137b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADn?= Date: Thu, 19 Sep 2024 08:15:12 +0200 Subject: [PATCH 55/56] Fix and add test --- .../roomlist/impl/RoomListPresenterTest.kt | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt index 8b7294b165..c77f59a0a8 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt @@ -85,13 +85,16 @@ import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +import kotlin.time.Duration.Companion.seconds class RoomListPresenterTest { @get:Rule @@ -599,6 +602,38 @@ class RoomListPresenterTest { } } + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `present - UpdateVisibleRange will cancel the previous subscription if called too soon`() = runTest { + val subscribeToVisibleRoomsLambda = lambdaRecorder { _: List -> } + val roomListService = FakeRoomListService(subscribeToVisibleRoomsLambda = subscribeToVisibleRoomsLambda) + val scope = CoroutineScope(coroutineContext + SupervisorJob()) + val matrixClient = FakeMatrixClient( + roomListService = roomListService, + ) + val roomSummary = aRoomSummary( + currentUserMembership = CurrentUserMembership.INVITED + ) + roomListService.postAllRoomsLoadingState(RoomList.LoadingState.Loaded(1)) + roomListService.postAllRooms(listOf(roomSummary)) + val presenter = createRoomListPresenter( + coroutineScope = scope, + client = matrixClient, + ) + presenter.test { + val state = consumeItemsUntilPredicate { + it.contentState is RoomListContentState.Rooms + }.last() + + state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 10))) + // If called again, it will cancel the current one, which should not result in a test failure + state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 11))) + advanceTimeBy(1.seconds) + subscribeToVisibleRoomsLambda.assertions().isCalledOnce() + } + } + + @OptIn(ExperimentalCoroutinesApi::class) @Test fun `present - UpdateVisibleRange subscribes to rooms in visible range`() = runTest { val subscribeToVisibleRoomsLambda = lambdaRecorder { _: List -> } @@ -622,10 +657,12 @@ class RoomListPresenterTest { }.last() state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 10))) + advanceTimeBy(1.seconds) subscribeToVisibleRoomsLambda.assertions().isCalledOnce() - // If called again, it will cancel the current one, which should not result in a test failure + // If called again, it will subscribe to the next items state.eventSink(RoomListEvents.UpdateVisibleRange(IntRange(0, 11))) + advanceTimeBy(1.seconds) subscribeToVisibleRoomsLambda.assertions().isCalledExactly(2) } } From 7eac45e4d26329147e6ea1b129eb6c19b3296b21 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 19 Sep 2024 10:36:33 +0200 Subject: [PATCH 56/56] Adding fastlane file for version 0.6.3 --- fastlane/metadata/android/en-US/changelogs/40006030.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/40006030.txt diff --git a/fastlane/metadata/android/en-US/changelogs/40006030.txt b/fastlane/metadata/android/en-US/changelogs/40006030.txt new file mode 100644 index 0000000000..0574894881 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40006030.txt @@ -0,0 +1,2 @@ +Element X is the new generation of Element for professional and personal use on mobile. It’s the fastest Matrix client with a seamless & intuitive user interface. +Full changelog: https://github.com/element-hq/element-x-android/releases