Add test skeleton for RustMatrixClientFactory and RustMatrixAuthenticationService

This commit is contained in:
Benoit Marty
2024-09-19 12:16:24 +02:00
parent b2abf0cf97
commit fc795c9be8
13 changed files with 280 additions and 1 deletions

View File

@@ -46,7 +46,9 @@ dependencies {
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
testImplementation(libs.test.robolectric)
testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.services.analytics.test)

View File

@@ -0,0 +1,23 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.AppScope
import org.matrix.rustcomponents.sdk.ClientBuilder
interface ClientBuilderProvider {
fun provide(): ClientBuilder
}
@ContributesBinding(AppScope::class)
class RustClientBuilderProvider : ClientBuilderProvider {
override fun provide(): ClientBuilder {
return ClientBuilder()
}
}

View File

@@ -47,6 +47,7 @@ class RustMatrixClientFactory @Inject constructor(
private val utdTracker: UtdTracker,
private val featureFlagService: FeatureFlagService,
private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
private val clientBuilderProvider: ClientBuilderProvider,
) {
suspend fun create(sessionData: SessionData): RustMatrixClient = withContext(coroutineDispatchers.io) {
val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers)
@@ -89,7 +90,7 @@ class RustMatrixClientFactory @Inject constructor(
passphrase: String?,
slidingSyncType: ClientBuilderSlidingSync,
): ClientBuilder {
return ClientBuilder()
return clientBuilderProvider.provide()
.sessionPaths(
dataPath = sessionPaths.fileDirectory.absolutePath,
cachePath = sessionPaths.cacheDirectory.absolutePath,

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeRustClientBuilder
import org.matrix.rustcomponents.sdk.ClientBuilder
class FakeClientBuilderProvider : ClientBuilderProvider {
override fun provide(): ClientBuilder {
return FakeRustClientBuilder()
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.analytics.UtdTracker
import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider
import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider
import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.File
class RustMatrixClientFactoryTest {
@Test
fun test() = runTest {
val sut = createRustMatrixClientFactory()
val result = sut.create(aSessionData())
assertThat(result.sessionId).isEqualTo(SessionId("@alice:server.org"))
result.close()
}
}
fun TestScope.createRustMatrixClientFactory(
baseDirectory: File = File("/base"),
cacheDirectory: File = File("/cache"),
sessionStore: SessionStore = InMemorySessionStore(),
) = RustMatrixClientFactory(
baseDirectory = baseDirectory,
cacheDirectory = cacheDirectory,
appCoroutineScope = this,
coroutineDispatchers = testCoroutineDispatchers(),
sessionStore = sessionStore,
userAgentProvider = SimpleUserAgentProvider(),
userCertificatesProvider = FakeUserCertificatesProvider(),
proxyProvider = FakeProxyProvider(),
clock = FakeSystemClock(),
utdTracker = UtdTracker(FakeAnalyticsService()),
featureFlagService = FakeFeatureFlagService(),
timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(),
clientBuilderProvider = FakeClientBuilderProvider(),
)

View File

@@ -0,0 +1,17 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator
import io.element.android.libraries.matrix.test.A_PASSPHRASE
class FakePassphraseGenerator(
private val passphrase: () -> String? = { A_PASSPHRASE }
) : PassphraseGenerator {
override fun generatePassphrase(): String? = passphrase()
}

View File

@@ -0,0 +1,16 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
class FakeProxyProvider : ProxyProvider {
override fun provides(): String? {
return null
}
}

View File

@@ -0,0 +1,16 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
class FakeUserCertificatesProvider : UserCertificatesProvider {
override fun provides(): List<ByteArray> {
return emptyList()
}
}

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.createRustMatrixClientFactory
import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Test
import java.io.File
class RustMatrixAuthenticationServiceTest {
@Test
fun `getLatestSessionId should return the value from the store`() = runTest {
val sessionStore = InMemorySessionStore()
val sut = createRustMatrixAuthenticationService(
sessionStore = sessionStore,
)
assertThat(sut.getLatestSessionId()).isNull()
sessionStore.storeData(aSessionData(sessionId = "@alice:server.org"))
assertThat(sut.getLatestSessionId()).isEqualTo(SessionId("@alice:server.org"))
}
private fun TestScope.createRustMatrixAuthenticationService(
sessionStore: SessionStore = InMemorySessionStore(),
): RustMatrixAuthenticationService {
val baseDirectory = File("/base")
val cacheDirectory = File("/cache")
val rustMatrixClientFactory = createRustMatrixClientFactory(
baseDirectory = baseDirectory,
cacheDirectory = cacheDirectory,
sessionStore = sessionStore,
)
return RustMatrixAuthenticationService(
sessionPathsFactory = SessionPathsFactory(baseDirectory, cacheDirectory),
coroutineDispatchers = testCoroutineDispatchers(),
sessionStore = sessionStore,
rustMatrixClientFactory = rustMatrixClientFactory,
passphraseGenerator = FakePassphraseGenerator(),
oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory),
appPreferencesStore = InMemoryAppPreferencesStore(),
)
}
}

View File

@@ -18,6 +18,7 @@ import org.matrix.rustcomponents.sdk.NotificationClient
import org.matrix.rustcomponents.sdk.NotificationProcessSetup
import org.matrix.rustcomponents.sdk.NotificationSettings
import org.matrix.rustcomponents.sdk.Session
import org.matrix.rustcomponents.sdk.SyncServiceBuilder
import org.matrix.rustcomponents.sdk.TaskHandle
class FakeRustClient(
@@ -36,4 +37,6 @@ class FakeRustClient(
override fun session(): Session = session
override fun setDelegate(delegate: ClientDelegate?): TaskHandle = FakeRustTaskHandle()
override fun cachedAvatarUrl(): String? = null
override suspend fun restoreSession(session: Session) = Unit
override fun syncService(): SyncServiceBuilder = FakeRustSyncServiceBuilder()
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.fakes
import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.ClientBuilder
import org.matrix.rustcomponents.sdk.ClientSessionDelegate
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.OidcConfiguration
import org.matrix.rustcomponents.sdk.QrCodeData
import org.matrix.rustcomponents.sdk.QrLoginProgressListener
import org.matrix.rustcomponents.sdk.RequestConfig
import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder
import uniffi.matrix_sdk.BackupDownloadStrategy
import uniffi.matrix_sdk_crypto.CollectStrategy
class FakeRustClientBuilder : ClientBuilder(NoPointer) {
override fun addRootCertificates(certificates: List<ByteArray>) = this
override fun autoEnableBackups(autoEnableBackups: Boolean) = this
override fun autoEnableCrossSigning(autoEnableCrossSigning: Boolean) = this
override fun backupDownloadStrategy(backupDownloadStrategy: BackupDownloadStrategy) = this
override fun disableAutomaticTokenRefresh() = this
override fun disableBuiltInRootCertificates() = this
override fun disableSslVerification() = this
override fun enableCrossProcessRefreshLock(processId: String, sessionDelegate: ClientSessionDelegate) = this
override fun homeserverUrl(url: String) = this
override fun passphrase(passphrase: String?) = this
override fun proxy(url: String) = this
override fun requestConfig(config: RequestConfig) = this
override fun roomKeyRecipientStrategy(strategy: CollectStrategy) = this
override fun serverName(serverName: String) = this
override fun serverNameOrHomeserverUrl(serverNameOrUrl: String) = this
override fun sessionPaths(dataPath: String, cachePath: String) = this
override fun setSessionDelegate(sessionDelegate: ClientSessionDelegate) = this
override fun slidingSyncVersionBuilder(versionBuilder: SlidingSyncVersionBuilder) = this
override fun userAgent(userAgent: String) = this
override fun username(username: String) = this
override suspend fun buildWithQrCode(qrCodeData: QrCodeData, oidcConfiguration: OidcConfiguration, progressListener: QrLoginProgressListener): Client {
return FakeRustClient()
}
override suspend fun build(): Client {
return FakeRustClient()
}
}

View File

@@ -0,0 +1,18 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.fixtures.fakes
import org.matrix.rustcomponents.sdk.NoPointer
import org.matrix.rustcomponents.sdk.SyncService
import org.matrix.rustcomponents.sdk.SyncServiceBuilder
import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate
class FakeRustSyncServiceBuilder : SyncServiceBuilder(NoPointer) {
override suspend fun withUtdHook(delegate: UnableToDecryptDelegate): SyncServiceBuilder = this
override suspend fun finish(): SyncService = FakeRustSyncService()
}

View File

@@ -23,6 +23,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
const val A_USER_NAME = "alice"
const val A_PASSWORD = "password"
const val A_PASSPHRASE = "passphrase"
const val A_SECRET = "secret"
val A_USER_ID = UserId("@alice:server.org")