Merge branch 'develop' into feature/fga/space_settings_iteration

This commit is contained in:
ganfra 2025-12-15 16:06:06 +01:00
commit ce079e84f5
600 changed files with 3591 additions and 2388 deletions

View file

@ -75,7 +75,10 @@ import io.element.android.libraries.matrix.impl.util.SessionPathsProvider
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
import io.element.android.libraries.matrix.impl.workmanager.PerformDatabaseVacuumWorkManagerRequest
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.collections.immutable.ImmutableList
@ -133,6 +136,7 @@ class RustMatrixClient(
timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
private val featureFlagService: FeatureFlagService,
private val analyticsService: AnalyticsService,
private val workManagerScheduler: WorkManagerScheduler,
) : MatrixClient {
override val sessionId: UserId = UserId(innerClient.userId())
override val deviceId: DeviceId = DeviceId(innerClient.deviceId())
@ -276,6 +280,9 @@ class RustMatrixClient(
// Force a refresh of the profile
getUserProfile()
}
// Schedule regular database vacuuming to ensure DB performance remains optimal
scheduleDatabaseVacuum()
}
override fun userIdServerName(): String {
@ -726,6 +733,13 @@ class RustMatrixClient(
}
}
override suspend fun performDatabaseVacuum(): Result<Unit> = withContext(sessionDispatcher) {
runCatchingExceptions {
Timber.d("Performing database vacuuming for session $sessionId...")
innerClient.optimizeStores()
}
}
private suspend fun getCacheSize(
includeCryptoDb: Boolean = false,
): Long = withContext(sessionDispatcher) {
@ -750,6 +764,15 @@ class RustMatrixClient(
// Delete all the files for this session
sessionPathsProvider.provides(sessionId)?.deleteRecursively()
}
private fun scheduleDatabaseVacuum() {
// If there's already a periodic work request, do not schedule another one
if (workManagerScheduler.hasPendingWork(sessionId, WorkManagerRequestType.DB_VACUUM)) return
Timber.i("Scheduling periodic database vacuuming for session $sessionId")
val request = PerformDatabaseVacuumWorkManagerRequest(sessionId)
workManagerScheduler.submit(request)
}
}
private val defaultRoomCreationPowerLevels = PowerLevels(

View file

@ -22,10 +22,12 @@ import io.element.android.libraries.matrix.impl.paths.SessionPaths
import io.element.android.libraries.matrix.impl.paths.getSessionPaths
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory
import io.element.android.libraries.matrix.impl.storage.SqliteStoreBuilderProvider
import io.element.android.libraries.matrix.impl.util.anonymizedTokens
import io.element.android.libraries.network.useragent.UserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.toolbox.api.systemclock.SystemClock
import kotlinx.coroutines.CoroutineScope
@ -36,7 +38,6 @@ import org.matrix.rustcomponents.sdk.RequestConfig
import org.matrix.rustcomponents.sdk.Session
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
import org.matrix.rustcomponents.sdk.use
import timber.log.Timber
import uniffi.matrix_sdk_base.MediaRetentionPolicy
@ -62,6 +63,8 @@ class RustMatrixClientFactory(
private val featureFlagService: FeatureFlagService,
private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
private val clientBuilderProvider: ClientBuilderProvider,
private val sqliteStoreBuilderProvider: SqliteStoreBuilderProvider,
private val workManagerScheduler: WorkManagerScheduler,
) {
private val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers)
@ -115,6 +118,7 @@ class RustMatrixClientFactory(
timelineEventTypeFilterFactory = timelineEventTypeFilterFactory,
featureFlagService = featureFlagService,
analyticsService = analyticsService,
workManagerScheduler = workManagerScheduler,
).also {
Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'")
}
@ -126,12 +130,11 @@ class RustMatrixClientFactory(
slidingSyncType: ClientBuilderSlidingSync,
): ClientBuilder {
return clientBuilderProvider.provide()
.sqliteStore(
SqliteStoreBuilder(
dataPath = sessionPaths.fileDirectory.absolutePath,
cachePath = sessionPaths.cacheDirectory.absolutePath,
).passphrase(passphrase)
)
.run {
sqliteStoreBuilderProvider.provide(sessionPaths)
.passphrase(passphrase)
.setupClientBuilder(this)
}
.setSessionDelegate(sessionDelegate)
.userAgent(userAgentProvider.provide())
.addRootCertificates(userCertificatesProvider.provides())

View file

@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.auth.OidcDetails
import io.element.android.libraries.matrix.api.auth.OidcPrompt
import io.element.android.libraries.matrix.api.auth.SessionRestorationException
import io.element.android.libraries.matrix.api.auth.external.ExternalSession
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
@ -91,10 +92,10 @@ class RustMatrixAuthenticationService(
}
rustMatrixClientFactory.create(sessionData)
} else {
error("Token is not valid")
throw SessionRestorationException.InvalidToken()
}
} else {
error("No session to restore with id $sessionId")
throw SessionRestorationException.MissingSession(sessionId)
}
}.mapFailure { failure ->
failure.mapClientException()

View file

@ -30,7 +30,7 @@ fun Throwable.mapRecoveryException(): RecoveryException {
}
}
else -> RecoveryException.Client(
ClientException.Other("Unknown error")
ClientException.Other("Unknown error", this)
)
}
}

View file

@ -15,15 +15,16 @@ fun Throwable.mapClientException(): ClientException {
return when (this) {
is RustClientException -> {
when (this) {
is RustClientException.Generic -> ClientException.Generic(msg, details)
is RustClientException.Generic -> ClientException.Generic(message = msg, details = details, cause = this)
is RustClientException.MatrixApi -> ClientException.MatrixApi(
kind = kind.map(),
code = code,
message = msg,
details = details,
cause = this,
)
}
}
else -> ClientException.Other(message ?: "Unknown error")
else -> ClientException.Other(message ?: "Unknown error", this)
}
}

View file

@ -34,7 +34,7 @@ class RoomSyncSubscriber(
}
subscribedRoomIds.add(roomId)
} catch (exception: Exception) {
Timber.e("Failed to subscribe to room $roomId")
Timber.e(exception, "Failed to subscribe to room $roomId")
}
}
}

View file

@ -85,7 +85,9 @@ class RustBaseRoom(
}.stateIn(roomCoroutineScope, started = SharingStarted.Lazily, initialValue = initialRoomInfo)
override fun predecessorRoom(): PredecessorRoom? {
return innerRoom.predecessorRoom()?.map()
return runCatchingExceptions { innerRoom.predecessorRoom()?.map() }
.onFailure { Timber.e(it, "Could not get predecessor room") }
.getOrNull()
}
override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId)

View file

@ -48,7 +48,7 @@ fun RoomListInterface.loadingStateFlow(): Flow<RoomListLoadingState> =
try {
send(result.state)
} catch (exception: Exception) {
Timber.d("loadingStateFlow() initialState failed.")
Timber.d(exception, "loadingStateFlow() initialState failed.")
}
result.stateStream
}.catch {

View file

@ -24,7 +24,7 @@ class RoomSummaryFactory(
) {
suspend fun create(room: Room): RoomSummary {
val roomInfo = room.roomInfo().let(roomInfoMapper::map)
val latestEvent = room.newLatestEvent().use { event ->
val latestEvent = room.latestEvent().use { event ->
when (event) {
is RustLatestEventValue.None -> LatestEventValue.None
is RustLatestEventValue.Local -> LatestEventValue.Local(

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.storage
import io.element.android.libraries.matrix.impl.paths.SessionPaths
import org.matrix.rustcomponents.sdk.ClientBuilder
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder
interface SqliteStoreBuilder {
fun passphrase(passphrase: String?): SqliteStoreBuilder
fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder
}
class RustSqliteStoreBuilder(
private val sessionPaths: SessionPaths,
) : SqliteStoreBuilder {
private var inner = SdkSqliteStoreBuilder(
dataPath = sessionPaths.fileDirectory.absolutePath,
cachePath = sessionPaths.cacheDirectory.absolutePath,
)
override fun passphrase(passphrase: String?): SqliteStoreBuilder {
inner = inner.passphrase(passphrase)
return this
}
override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder {
return clientBuilder.sqliteStore(this.inner)
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.storage
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.impl.paths.SessionPaths
interface SqliteStoreBuilderProvider {
fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder
}
@ContributesBinding(AppScope::class)
class RustSqliteStoreBuilderProvider : SqliteStoreBuilderProvider {
override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder {
return RustSqliteStoreBuilder(sessionPaths)
}
}

View file

@ -16,6 +16,8 @@ fun TraceLogPack.map(): RustTraceLogPack = when (this) {
TraceLogPack.EVENT_CACHE -> RustTraceLogPack.EVENT_CACHE
TraceLogPack.TIMELINE -> RustTraceLogPack.TIMELINE
TraceLogPack.NOTIFICATION_CLIENT -> RustTraceLogPack.NOTIFICATION_CLIENT
TraceLogPack.LATEST_EVENTS -> RustTraceLogPack.LATEST_EVENTS
TraceLogPack.SYNC_PROFILING -> RustTraceLogPack.SYNC_PROFILING
}
fun Collection<TraceLogPack>.map(): List<RustTraceLogPack> {

View file

@ -14,10 +14,10 @@ import timber.log.Timber
fun logError(throwable: Throwable) {
when (throwable) {
is ClientException.Generic -> {
Timber.e("Error ${throwable.msg}", throwable)
Timber.e(throwable, "Error ${throwable.msg}")
}
else -> {
Timber.e("Error", throwable)
Timber.e(throwable, "Error")
}
}
}

View file

@ -62,7 +62,7 @@ class RustWidgetDriver(
override suspend fun send(message: String) {
try {
driverAndHandle.handle.send(message)
} catch (e: IllegalStateException) {
} catch (_: IllegalStateException) {
// The handle is closed, ignore
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.workmanager
import androidx.work.Constraints
import androidx.work.Data
import androidx.work.PeriodicWorkRequest
import androidx.work.WorkRequest
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.workmanager.VacuumDatabaseWorker.Companion.SESSION_ID_PARAM
import io.element.android.libraries.workmanager.api.WorkManagerRequest
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
import io.element.android.libraries.workmanager.api.workManagerTag
import java.util.concurrent.TimeUnit
class PerformDatabaseVacuumWorkManagerRequest(
private val sessionId: SessionId,
) : WorkManagerRequest {
override fun build(): Result<List<WorkRequest>> {
val data = Data.Builder().putString(SESSION_ID_PARAM, sessionId.value).build()
val workRequest = PeriodicWorkRequest.Builder(
workerClass = VacuumDatabaseWorker::class,
// Run once a day
repeatInterval = 1,
repeatIntervalTimeUnit = TimeUnit.DAYS,
)
.addTag(workManagerTag(sessionId, WorkManagerRequestType.DB_VACUUM))
.setInputData(data)
// Only run when the device is idle to avoid impacting user experience
.setConstraints(Constraints.Builder().setRequiresDeviceIdle(true).build())
.build()
return Result.success(listOf(workRequest))
}
}

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.workmanager
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject
import dev.zacsweers.metro.ContributesIntoMap
import dev.zacsweers.metro.binding
import io.element.android.libraries.di.annotations.ApplicationContext
import io.element.android.libraries.matrix.api.MatrixClientProvider
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory
import io.element.android.libraries.workmanager.api.di.WorkerKey
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.api.recordTransaction
import timber.log.Timber
@AssistedInject
class VacuumDatabaseWorker(
@Assisted workerParams: WorkerParameters,
@ApplicationContext private val context: Context,
private val matrixClientProvider: MatrixClientProvider,
private val analyticsService: AnalyticsService,
) : CoroutineWorker(context, workerParams) {
companion object {
const val SESSION_ID_PARAM = "session_id"
}
override suspend fun doWork(): Result {
Timber.d("Starting database vacuuming...")
val sessionId = inputData.getString(SESSION_ID_PARAM)?.let(::SessionId) ?: return Result.failure()
val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return Result.failure()
return analyticsService.recordTransaction("Vacuuming DBs", "vacuuming") { transaction ->
client.performDatabaseVacuum()
.fold(
onSuccess = {
Timber.d("Database vacuuming finished successfully")
Result.success()
},
onFailure = { error ->
transaction.attachError(error)
Timber.e(error, "Database vacuuming failed")
Result.failure()
}
)
}
}
@ContributesIntoMap(AppScope::class, binding = binding<MetroWorkerFactory.WorkerInstanceFactory<*>>())
@WorkerKey(VacuumDatabaseWorker::class)
@AssistedFactory
interface Factory : MetroWorkerFactory.WorkerInstanceFactory<VacuumDatabaseWorker>
}

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl
import org.matrix.rustcomponents.sdk.NoHandle
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
class FakeFfiSqliteStoreBuilder : SqliteStoreBuilder(NoHandle) {
override fun cacheSize(cacheSize: UInt?): SqliteStoreBuilder = this
override fun journalSizeLimit(limit: UInt?): SqliteStoreBuilder = this
override fun passphrase(passphrase: String?): SqliteStoreBuilder = this
override fun poolMaxSize(poolMaxSize: UInt?): SqliteStoreBuilder = this
override fun systemIsMemoryConstrained(): SqliteStoreBuilder = this
}

View file

@ -14,26 +14,33 @@ import io.element.android.libraries.matrix.api.core.SessionId
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.matrix.impl.storage.FakeSqliteStoreBuilderProvider
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.libraries.workmanager.api.WorkManagerRequest
import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import java.io.File
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustMatrixClientFactoryTest {
@Test
fun test() = runTest {
val sut = createRustMatrixClientFactory()
val scheduleVacuumLambda = lambdaRecorder<WorkManagerRequest, Unit> {}
val workManagerScheduler = FakeWorkManagerScheduler(submitLambda = scheduleVacuumLambda)
val sut = createRustMatrixClientFactory(workManagerScheduler = workManagerScheduler)
val result = sut.create(aSessionData())
assertThat(result.sessionId).isEqualTo(SessionId("@alice:server.org"))
scheduleVacuumLambda.assertions().isCalledOnce()
result.destroy()
}
}
@ -44,6 +51,7 @@ fun TestScope.createRustMatrixClientFactory(
updateUserProfileResult = { _, _, _ -> },
),
clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(),
workManagerScheduler: FakeWorkManagerScheduler = FakeWorkManagerScheduler(),
) = RustMatrixClientFactory(
cacheDirectory = cacheDirectory,
appCoroutineScope = backgroundScope,
@ -57,4 +65,6 @@ fun TestScope.createRustMatrixClientFactory(
featureFlagService = FakeFeatureFlagService(),
timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(),
clientBuilderProvider = clientBuilderProvider,
sqliteStoreBuilderProvider = FakeSqliteStoreBuilderProvider(),
workManagerScheduler = workManagerScheduler,
)

View file

@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import io.element.android.tests.testutils.lambda.lambdaRecorder
@ -31,13 +32,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.UserProfile
import java.io.File
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustMatrixClientTest {
@Test
fun `ensure that sessionId and deviceId can be retrieved from the client`() = runTest {
@ -118,5 +117,6 @@ class RustMatrixClientTest {
timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(),
featureFlagService = FakeFeatureFlagService(),
analyticsService = FakeAnalyticsService(),
workManagerScheduler = FakeWorkManagerScheduler(submitLambda = {}),
)
}

View file

@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class HomeserverDetailsKtTest {
@Test
fun `map should be correct`() {

View file

@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustHomeserverLoginCompatibilityCheckerTest {
@Test
fun `check - is valid if it supports OIDC login`() = runTest {

View file

@ -23,12 +23,10 @@ import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import java.io.File
class RustMatrixAuthenticationServiceTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
fun `setHomeserver is successful`() = runTest {
val sut = createRustMatrixAuthenticationService(

View file

@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth.qrlogin
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class SdkQrCodeLoginDataTest {
@Test
fun `getServer reads the value from the Rust side, null case`() {

View file

@ -33,6 +33,7 @@ import org.matrix.rustcomponents.sdk.SyncServiceBuilder
import org.matrix.rustcomponents.sdk.TaskHandle
import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate
import org.matrix.rustcomponents.sdk.UserProfile
import uniffi.matrix_sdk_base.MediaRetentionPolicy
class FakeFfiClient(
private val userId: String = A_USER_ID.value,
@ -88,5 +89,7 @@ class FakeFfiClient(
return homeserverLoginDetailsResult()
}
override suspend fun setMediaRetentionPolicy(policy: MediaRetentionPolicy) {}
override fun close() = closeResult()
}

View file

@ -44,5 +44,6 @@ class FakeFfiClientBuilder(
override fun enableShareHistoryOnInvite(enableShareHistoryOnInvite: Boolean): ClientBuilder = this
override fun threadsEnabled(enabled: Boolean, threadSubscriptions: Boolean): ClientBuilder = this
override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this
override fun inMemoryStore(): ClientBuilder = this
override suspend fun build() = buildResult()
}

View file

@ -12,7 +12,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.tests.testutils.lambda.lambdaError
import org.matrix.rustcomponents.sdk.EventTimelineItem
import org.matrix.rustcomponents.sdk.LatestEventValue
import org.matrix.rustcomponents.sdk.NoHandle
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.RoomInfo
@ -24,7 +24,7 @@ class FakeFfiRoom(
private val getMembers: () -> RoomMembersIterator = { lambdaError() },
private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() },
private val leaveLambda: () -> Unit = { lambdaError() },
private val latestEventLambda: () -> EventTimelineItem? = { lambdaError() },
private val latestEventLambda: () -> LatestEventValue = { lambdaError() },
private val suggestedRoleForUserLambda: (String) -> RoomMemberRole = { lambdaError() },
private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value),
) : Room(NoHandle) {
@ -48,7 +48,7 @@ class FakeFfiRoom(
return roomInfo
}
override suspend fun latestEvent(): EventTimelineItem? {
override suspend fun latestEvent(): LatestEventValue {
return latestEventLambda()
}

View file

@ -29,15 +29,13 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.NotificationClient
import org.matrix.rustcomponents.sdk.NotificationStatus
import org.matrix.rustcomponents.sdk.TimelineEventType
class RustNotificationServiceTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun test() = runTest {
val notificationClient = FakeFfiNotificationClient(
notificationItemResult = mapOf(AN_EVENT_ID.value to aRustBatchNotificationResult()),
@ -58,8 +56,7 @@ class RustNotificationServiceTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `test mapping invalid item only drops that item`() = runTest {
val error = IllegalStateException("This event type is not supported")
val faultyEvent = object : FakeFfiTimelineEvent() {
@ -86,8 +83,7 @@ class RustNotificationServiceTest {
assertThat(successfulResult?.isSuccess).isTrue()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `test unable to resolve event`() = runTest {
val notificationClient = FakeFfiNotificationClient(
notificationItemResult = emptyMap(),
@ -99,8 +95,7 @@ class RustNotificationServiceTest {
assertThat(exception).isInstanceOf(NotificationResolverException::class.java)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `close should invoke the close method of the service`() = runTest {
val closeResult = lambdaRecorder<Unit> { }
val notificationClient = FakeFfiNotificationClient(

View file

@ -16,13 +16,11 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.NotificationSettings
class RustNotificationSettingsServiceTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun test() = runTest {
val sut = createRustNotificationSettingsService()
val result = sut.getRoomNotificationSettings(

View file

@ -13,10 +13,8 @@ import io.element.android.libraries.matrix.api.pusher.UnsetHttpPusherData
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustPushersServiceTest {
@Test
fun `setPusher should invoke the client method`() = runTest {

View file

@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
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.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RoomInfoExtTest {
@Test
fun `get non empty element Heroes`() {

View file

@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevelValues
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toImmutableList
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.Membership
import uniffi.matrix_sdk_base.EncryptionState
@ -40,7 +39,6 @@ import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RoomInfoMapperTest {
@Test
fun `mapping of RustRoomInfo should map all the fields`() {

View file

@ -31,11 +31,9 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.isActive
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import uniffi.matrix_sdk.RoomMemberRole
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustBaseRoomTest {
@Test
fun `RustBaseRoom should cancel the room coroutine scope when it is destroyed`() = runTest {

View file

@ -25,10 +25,8 @@ import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class DefaultJoinRoomTest {
@Test
fun `when using roomId and there is no server names, the classic join room API is used`() = runTest {

View file

@ -24,10 +24,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_4
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RoomMemberListFetcherTest {
@Test
fun `fetchRoomMembers with CACHE source - emits cached members, if any`() = runTest {

View file

@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.RoomDirectorySearch
import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@OptIn(ExperimentalCoroutinesApi::class)
class RustBaseRoomDirectoryListTest {
@Test

View file

@ -11,12 +11,10 @@ package io.element.android.libraries.matrix.impl.roomdirectory
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
class RustBaseRoomDirectoryServiceTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun test() = runTest {
val client = FakeFfiClient()
val sut = RustRoomDirectoryService(

View file

@ -12,13 +12,11 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomList
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomListService
import io.element.android.services.analytics.test.FakeAnalyticsService
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import kotlin.coroutines.EmptyCoroutineContext
class RoomListFactoryTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `createRoomList should work`() = runTest {
val sut = RoomListFactory(
innerRoomListService = FakeFfiRoomListService(),

View file

@ -21,15 +21,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.LatestEventValue
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
class RoomSummaryListProcessorTest {
private val summaries = MutableStateFlow<List<RoomSummary>>(emptyList())
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Append adds new entries at the end of the list`() = runTest {
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
@ -41,8 +40,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushBack adds a new entry at the end of the list`() = runTest {
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
@ -52,8 +50,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushFront inserts a new entry at the start of the list`() = runTest {
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
@ -63,8 +60,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Set replaces an entry at some index`() = runTest {
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
@ -76,8 +72,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Insert inserts a new entry at the provided index`() = runTest {
summaries.value = listOf(aRoomSummary())
val processor = createProcessor()
@ -89,8 +84,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Remove removes an entry at some index`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -105,8 +99,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopBack removes an entry at the end of the list`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -121,8 +114,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopFront removes an entry at the start of the list`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -137,8 +129,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Clear removes all the entries`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -151,8 +142,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value).isEmpty()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Truncate removes all entries after the provided length`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -167,8 +157,7 @@ class RoomSummaryListProcessorTest {
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Reset removes all entries and add the provided ones`() = runTest {
summaries.value = listOf(
aRoomSummary(roomId = A_ROOM_ID),
@ -185,7 +174,7 @@ class RoomSummaryListProcessorTest {
private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeFfiRoom(
roomId = roomId,
latestEventLambda = { null },
latestEventLambda = { LatestEventValue.None }
)
private fun TestScope.createProcessor() = RoomSummaryListProcessor(

View file

@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator
import org.matrix.rustcomponents.sdk.RoomListService as RustRoomListService
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@OptIn(ExperimentalCoroutinesApi::class)
class RustBaseRoomListServiceTest {
@Test

View file

@ -18,15 +18,13 @@ import io.element.android.libraries.previewutils.room.aSpaceRoom
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.SpaceListUpdate
class RoomSummaryListProcessorTest {
private val spaceRoomsFlow = MutableStateFlow<List<SpaceRoom>>(emptyList())
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Append adds new entries at the end of the list`() = runTest {
spaceRoomsFlow.value = listOf(aSpaceRoom())
val processor = createProcessor()
@ -38,8 +36,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushBack adds a new entry at the end of the list`() = runTest {
spaceRoomsFlow.value = listOf(aSpaceRoom())
val processor = createProcessor()
@ -49,8 +46,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value.last().roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushFront inserts a new entry at the start of the list`() = runTest {
spaceRoomsFlow.value = listOf(aSpaceRoom())
val processor = createProcessor()
@ -60,8 +56,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value.first().roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Set replaces an entry at some index`() = runTest {
spaceRoomsFlow.value = listOf(aSpaceRoom())
val processor = createProcessor()
@ -73,8 +68,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Insert inserts a new entry at the provided index`() = runTest {
spaceRoomsFlow.value = listOf(aSpaceRoom())
val processor = createProcessor()
@ -86,8 +80,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Remove removes an entry at some index`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -102,8 +95,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopBack removes an entry at the end of the list`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -118,8 +110,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopFront removes an entry at the start of the list`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -134,8 +125,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Clear removes all the entries`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -148,8 +138,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value).isEmpty()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Truncate removes all entries after the provided length`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -164,8 +153,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Reset removes all entries and add the provided ones`() = runTest {
spaceRoomsFlow.value = listOf(
aSpaceRoom(roomId = A_ROOM_ID),
@ -180,8 +168,7 @@ class RoomSummaryListProcessorTest {
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_3)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `When there is no replay cache SpaceListUpdateProcessor starts with an empty list`() = runTest {
val spaceRoomsSharedFlow = MutableSharedFlow<List<SpaceRoom>>(replay = 1)
val processor = createProcessor(

View file

@ -23,15 +23,13 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.SpaceListUpdate
import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState
import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList
class RustSpaceRoomListTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `paginationStatusFlow emits values`() = runTest {
val innerSpaceRoomList = FakeFfiSpaceRoomList(
paginationStateResult = { SpaceRoomListPaginationState.Idle(false) }
@ -53,8 +51,7 @@ class RustSpaceRoomListTest {
}
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `spaceRoomsFlow emits values`() = runTest {
val innerSpaceRoomList = FakeFfiSpaceRoomList(
paginationStateResult = { SpaceRoomListPaginationState.Idle(false) }
@ -76,8 +73,7 @@ class RustSpaceRoomListTest {
}
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `paginate invokes paginate on the inner class`() = runTest {
val paginateResult = lambdaRecorder<Unit> { }
val innerSpaceRoomList = FakeFfiSpaceRoomList(

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.storage
import org.matrix.rustcomponents.sdk.ClientBuilder
class FakeSqliteStoreBuilder : SqliteStoreBuilder {
override fun passphrase(passphrase: String?): SqliteStoreBuilder = this
override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder {
return clientBuilder
}
}

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.storage
import io.element.android.libraries.matrix.impl.paths.SessionPaths
class FakeSqliteStoreBuilderProvider : SqliteStoreBuilderProvider {
override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder {
return FakeSqliteStoreBuilder()
}
}

View file

@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.TimelineDiff
@ -31,8 +30,7 @@ class MatrixTimelineDiffProcessorTest {
private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())
private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem())
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Append adds new entries at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -44,8 +42,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushBack adds a new entry at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -57,8 +54,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PushFront inserts a new entry at the start of the list`() = runTest {
timelineItems.value = listOf(anEvent)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -70,8 +66,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Set replaces an entry at some index`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -83,8 +78,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Insert inserts a new entry at the provided index`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -97,8 +91,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Remove removes an entry at some index`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -110,8 +103,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopBack removes an entry at the end of the list`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -122,8 +114,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `PopFront removes an entry at the start of the list`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -134,8 +125,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Clear removes all the entries`() = runTest {
timelineItems.value = listOf(anEvent, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -143,8 +133,7 @@ class MatrixTimelineDiffProcessorTest {
assertThat(timelineItems.value).isEmpty()
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Truncate removes all entries after the provided length`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)
@ -155,8 +144,7 @@ class MatrixTimelineDiffProcessorTest {
)
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `Reset removes all entries and add the provided ones`() = runTest {
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
val processor = createMatrixTimelineDiffProcessor(timelineItems)

View file

@ -30,13 +30,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.TimelineDiff
import uniffi.matrix_sdk.RoomPaginationStatus
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
class RustTimelineTest {
@Test
fun `ensure that the timeline emits new loading item when pagination does not bring new events`() = runTest {

View file

@ -20,7 +20,6 @@ import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import org.matrix.rustcomponents.sdk.Timeline
import org.matrix.rustcomponents.sdk.TimelineDiff
@ -28,8 +27,7 @@ import uniffi.matrix_sdk_ui.EventItemOrigin
@OptIn(ExperimentalCoroutinesApi::class)
class TimelineItemsSubscriberTest {
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `when timeline emits an empty list of items, the flow must emits an empty list`() = runTest {
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
@ -52,8 +50,7 @@ class TimelineItemsSubscriberTest {
}
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `when timeline emits a non empty list of items, the flow must emits a non empty list`() = runTest {
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
@ -76,8 +73,7 @@ class TimelineItemsSubscriberTest {
}
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `when timeline emits an item with SYNC origin`() = runTest {
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
@ -108,8 +104,7 @@ class TimelineItemsSubscriberTest {
}
}
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
@Test
@Test
fun `multiple subscriptions does not have side effect`() = runTest {
val timelineItemsSubscriber = createTimelineItemsSubscriber()
timelineItemsSubscriber.subscribeIfNeeded()