mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2025-02-16 12:00:03 +03:00
Merge pull request #7754 from vector-im/feature/ons/remove_client_information_account_data
Delete unused client information from account data (PSG-871)
This commit is contained in:
commit
250bd9c620
13 changed files with 360 additions and 1 deletions
1
changelog.d/7754.feature
Normal file
1
changelog.d/7754.feature
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Delete unused client information from account data
|
|
@ -63,4 +63,17 @@ interface SessionAccountDataService {
|
||||||
* Update the account data with the provided type and the provided account data content.
|
* Update the account data with the provided type and the provided account data content.
|
||||||
*/
|
*/
|
||||||
suspend fun updateUserAccountData(type: String, content: Content)
|
suspend fun updateUserAccountData(type: String, content: Content)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve user account data list whose type starts with the given type.
|
||||||
|
* @param type the type or the starting part of a type
|
||||||
|
* @return list of account data whose type starts with the given type
|
||||||
|
*/
|
||||||
|
fun getUserAccountDataEventsStartWith(type: String): List<UserAccountDataEvent>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes user account data of the given type.
|
||||||
|
* @param type the type to delete from user account data
|
||||||
|
*/
|
||||||
|
suspend fun deleteUserAccountData(type: String)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,4 +42,7 @@ internal abstract class AccountDataModule {
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
abstract fun bindUpdateBreadcrumbsTask(task: DefaultUpdateBreadcrumbsTask): UpdateBreadcrumbsTask
|
abstract fun bindUpdateBreadcrumbsTask(task: DefaultUpdateBreadcrumbsTask): UpdateBreadcrumbsTask
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract fun bindDeleteUserAccountDataTask(task: DefaultDeleteUserAccountDataTask): DeleteUserAccountDataTask
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,11 @@ import javax.inject.Inject
|
||||||
internal class DefaultSessionAccountDataService @Inject constructor(
|
internal class DefaultSessionAccountDataService @Inject constructor(
|
||||||
@SessionDatabase private val monarchy: Monarchy,
|
@SessionDatabase private val monarchy: Monarchy,
|
||||||
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
private val updateUserAccountDataTask: UpdateUserAccountDataTask,
|
||||||
|
private val deleteUserAccountDataTask: DeleteUserAccountDataTask,
|
||||||
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
private val userAccountDataSyncHandler: UserAccountDataSyncHandler,
|
||||||
private val userAccountDataDataSource: UserAccountDataDataSource,
|
private val userAccountDataDataSource: UserAccountDataDataSource,
|
||||||
private val roomAccountDataDataSource: RoomAccountDataDataSource,
|
private val roomAccountDataDataSource: RoomAccountDataDataSource,
|
||||||
private val taskExecutor: TaskExecutor
|
private val taskExecutor: TaskExecutor,
|
||||||
) : SessionAccountDataService {
|
) : SessionAccountDataService {
|
||||||
|
|
||||||
override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? {
|
override fun getUserAccountDataEvent(type: String): UserAccountDataEvent? {
|
||||||
|
@ -78,4 +79,12 @@ internal class DefaultSessionAccountDataService @Inject constructor(
|
||||||
userAccountDataSyncHandler.handleGenericAccountData(realm, type, content)
|
userAccountDataSyncHandler.handleGenericAccountData(realm, type, content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getUserAccountDataEventsStartWith(type: String): List<UserAccountDataEvent> {
|
||||||
|
return userAccountDataDataSource.getAccountDataEventsStartWith(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun deleteUserAccountData(type: String) {
|
||||||
|
deleteUserAccountDataTask.execute(DeleteUserAccountDataTask.Params(type))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.user.accountdata
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.internal.di.UserId
|
||||||
|
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
|
||||||
|
import org.matrix.android.sdk.internal.network.executeRequest
|
||||||
|
import org.matrix.android.sdk.internal.task.Task
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal interface DeleteUserAccountDataTask : Task<DeleteUserAccountDataTask.Params, Unit> {
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val type: String,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultDeleteUserAccountDataTask @Inject constructor(
|
||||||
|
private val accountDataApi: AccountDataAPI,
|
||||||
|
@UserId private val userId: String,
|
||||||
|
private val globalErrorReceiver: GlobalErrorReceiver,
|
||||||
|
) : DeleteUserAccountDataTask {
|
||||||
|
|
||||||
|
override suspend fun execute(params: DeleteUserAccountDataTask.Params) {
|
||||||
|
return executeRequest(globalErrorReceiver) {
|
||||||
|
accountDataApi.deleteAccountData(userId, params.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,6 +60,16 @@ internal class UserAccountDataDataSource @Inject constructor(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getAccountDataEventsStartWith(type: String): List<UserAccountDataEvent> {
|
||||||
|
return realmSessionProvider.withRealm { realm ->
|
||||||
|
realm
|
||||||
|
.where(UserAccountDataEntity::class.java)
|
||||||
|
.beginsWith(UserAccountDataEntityFields.TYPE, type)
|
||||||
|
.findAll()
|
||||||
|
.map(accountDataMapper::map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun accountDataEventsQuery(realm: Realm, types: Set<String>): RealmQuery<UserAccountDataEntity> {
|
private fun accountDataEventsQuery(realm: Realm, types: Set<String>): RealmQuery<UserAccountDataEntity> {
|
||||||
val query = realm.where(UserAccountDataEntity::class.java)
|
val query = realm.where(UserAccountDataEntity::class.java)
|
||||||
if (types.isNotEmpty()) {
|
if (types.isNotEmpty()) {
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.internal.session.user.accountdata
|
||||||
|
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.test.fakes.FakeAccountDataApi
|
||||||
|
import org.matrix.android.sdk.test.fakes.FakeGlobalErrorReceiver
|
||||||
|
|
||||||
|
private const val A_TYPE = "a-type"
|
||||||
|
private const val A_USER_ID = "a-user-id"
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
class DefaultDeleteUserAccountDataTaskTest {
|
||||||
|
|
||||||
|
private val fakeGlobalErrorReceiver = FakeGlobalErrorReceiver()
|
||||||
|
private val fakeAccountDataApi = FakeAccountDataApi()
|
||||||
|
|
||||||
|
private val deleteUserAccountDataTask = DefaultDeleteUserAccountDataTask(
|
||||||
|
accountDataApi = fakeAccountDataApi.instance,
|
||||||
|
userId = A_USER_ID,
|
||||||
|
globalErrorReceiver = fakeGlobalErrorReceiver
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given parameters when executing the task then api is called`() = runTest {
|
||||||
|
// Given
|
||||||
|
val params = DeleteUserAccountDataTask.Params(type = A_TYPE)
|
||||||
|
fakeAccountDataApi.givenParamsToDeleteAccountData(A_USER_ID, A_TYPE)
|
||||||
|
|
||||||
|
// When
|
||||||
|
deleteUserAccountDataTask.execute(params)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
coVerify { fakeAccountDataApi.instance.deleteAccountData(A_USER_ID, A_TYPE) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.matrix.android.sdk.test.fakes
|
||||||
|
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.just
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.runs
|
||||||
|
import org.matrix.android.sdk.internal.session.user.accountdata.AccountDataAPI
|
||||||
|
|
||||||
|
internal class FakeAccountDataApi {
|
||||||
|
|
||||||
|
val instance: AccountDataAPI = mockk()
|
||||||
|
|
||||||
|
fun givenParamsToDeleteAccountData(userId: String, type: String) {
|
||||||
|
coEvery { instance.deleteAccountData(userId, type) } just runs
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.session.clientinfo
|
||||||
|
|
||||||
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class DeleteUnusedClientInformationUseCase @Inject constructor(
|
||||||
|
private val activeSessionHolder: ActiveSessionHolder,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun execute(deviceInfoList: List<DeviceInfo>): Result<Unit> = runCatching {
|
||||||
|
// A defensive approach against local storage reports an empty device list (although it is not a seen situation).
|
||||||
|
if (deviceInfoList.isEmpty()) return Result.success(Unit)
|
||||||
|
|
||||||
|
val expectedClientInfoKeyList = deviceInfoList.map { MATRIX_CLIENT_INFO_KEY_PREFIX + it.deviceId }
|
||||||
|
activeSessionHolder
|
||||||
|
.getSafeActiveSession()
|
||||||
|
?.accountDataService()
|
||||||
|
?.getUserAccountDataEventsStartWith(MATRIX_CLIENT_INFO_KEY_PREFIX)
|
||||||
|
?.map { it.type }
|
||||||
|
?.subtract(expectedClientInfoKeyList.toSet())
|
||||||
|
?.forEach { userAccountDataKeyToDelete ->
|
||||||
|
activeSessionHolder.getSafeActiveSession()?.accountDataService()?.deleteUserAccountData(userAccountDataKeyToDelete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,12 +31,14 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||||
import im.vector.app.core.platform.EmptyViewEvents
|
import im.vector.app.core.platform.EmptyViewEvents
|
||||||
import im.vector.app.core.platform.VectorViewModel
|
import im.vector.app.core.platform.VectorViewModel
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
import im.vector.app.core.session.clientinfo.DeleteUnusedClientInformationUseCase
|
||||||
import im.vector.app.core.time.Clock
|
import im.vector.app.core.time.Clock
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.sample
|
import kotlinx.coroutines.flow.sample
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
@ -66,6 +68,7 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(
|
||||||
private val setUnverifiedSessionsAlertShownUseCase: SetUnverifiedSessionsAlertShownUseCase,
|
private val setUnverifiedSessionsAlertShownUseCase: SetUnverifiedSessionsAlertShownUseCase,
|
||||||
private val isNewLoginAlertShownUseCase: IsNewLoginAlertShownUseCase,
|
private val isNewLoginAlertShownUseCase: IsNewLoginAlertShownUseCase,
|
||||||
private val setNewLoginAlertShownUseCase: SetNewLoginAlertShownUseCase,
|
private val setNewLoginAlertShownUseCase: SetNewLoginAlertShownUseCase,
|
||||||
|
private val deleteUnusedClientInformationUseCase: DeleteUnusedClientInformationUseCase,
|
||||||
) : VectorViewModel<UnknownDevicesState, UnknownDeviceDetectorSharedViewModel.Action, EmptyViewEvents>(initialState) {
|
) : VectorViewModel<UnknownDevicesState, UnknownDeviceDetectorSharedViewModel.Action, EmptyViewEvents>(initialState) {
|
||||||
|
|
||||||
sealed class Action : VectorViewModelAction {
|
sealed class Action : VectorViewModelAction {
|
||||||
|
@ -102,6 +105,9 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(
|
||||||
) { cryptoList, infoList, pInfo ->
|
) { cryptoList, infoList, pInfo ->
|
||||||
// Timber.v("## Detector trigger ${cryptoList.map { "${it.deviceId} ${it.trustLevel}" }}")
|
// Timber.v("## Detector trigger ${cryptoList.map { "${it.deviceId} ${it.trustLevel}" }}")
|
||||||
// Timber.v("## Detector trigger canCrossSign ${pInfo.get().selfSigned != null}")
|
// Timber.v("## Detector trigger canCrossSign ${pInfo.get().selfSigned != null}")
|
||||||
|
|
||||||
|
deleteUnusedClientInformation(infoList)
|
||||||
|
|
||||||
infoList
|
infoList
|
||||||
.filter { info ->
|
.filter { info ->
|
||||||
// filter out verified sessions or those which do not support encryption (i.e. without crypto info)
|
// filter out verified sessions or those which do not support encryption (i.e. without crypto info)
|
||||||
|
@ -143,6 +149,12 @@ class UnknownDeviceDetectorSharedViewModel @AssistedInject constructor(
|
||||||
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
session.cryptoService().fetchDevicesList(NoOpMatrixCallback())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun deleteUnusedClientInformation(deviceFullInfoList: List<DeviceInfo>) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
deleteUnusedClientInformationUseCase.execute(deviceFullInfoList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun handle(action: Action) {
|
override fun handle(action: Action) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is Action.IgnoreDevice -> {
|
is Action.IgnoreDevice -> {
|
||||||
|
|
|
@ -112,6 +112,7 @@ class DevicesViewModel @AssistedInject constructor(
|
||||||
val deviceFullInfoList = async.invoke()
|
val deviceFullInfoList = async.invoke()
|
||||||
val unverifiedSessionsCount = deviceFullInfoList.count { !it.cryptoDeviceInfo?.trustLevel?.isCrossSigningVerified().orFalse() }
|
val unverifiedSessionsCount = deviceFullInfoList.count { !it.cryptoDeviceInfo?.trustLevel?.isCrossSigningVerified().orFalse() }
|
||||||
val inactiveSessionsCount = deviceFullInfoList.count { it.isInactive }
|
val inactiveSessionsCount = deviceFullInfoList.count { it.isInactive }
|
||||||
|
|
||||||
copy(
|
copy(
|
||||||
devices = async,
|
devices = async,
|
||||||
unverifiedSessionsCount = unverifiedSessionsCount,
|
unverifiedSessionsCount = unverifiedSessionsCount,
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.app.core.session.clientinfo
|
||||||
|
|
||||||
|
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
|
||||||
|
import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
|
||||||
|
|
||||||
|
private const val A_CURRENT_DEVICE_ID = "current-device-id"
|
||||||
|
private const val A_DEVICE_ID_1 = "a-device-id-1"
|
||||||
|
private const val A_DEVICE_ID_2 = "a-device-id-2"
|
||||||
|
private const val A_DEVICE_ID_3 = "a-device-id-3"
|
||||||
|
private const val A_DEVICE_ID_4 = "a-device-id-4"
|
||||||
|
|
||||||
|
private val A_DEVICE_INFO_1 = DeviceInfo(deviceId = A_DEVICE_ID_1)
|
||||||
|
private val A_DEVICE_INFO_2 = DeviceInfo(deviceId = A_DEVICE_ID_2)
|
||||||
|
|
||||||
|
class DeleteUnusedClientInformationUseCaseTest {
|
||||||
|
|
||||||
|
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
|
||||||
|
|
||||||
|
private val deleteUnusedClientInformationUseCase = DeleteUnusedClientInformationUseCase(
|
||||||
|
activeSessionHolder = fakeActiveSessionHolder.instance,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
fakeActiveSessionHolder.fakeSession.givenSessionId(A_CURRENT_DEVICE_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a device list that account data has all of them and extra devices then use case deletes the unused ones`() = runTest {
|
||||||
|
// Given
|
||||||
|
val devices = listOf(A_DEVICE_INFO_1, A_DEVICE_INFO_2)
|
||||||
|
val userAccountDataEventList = listOf(
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_1, mapOf("key" to "value")),
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_2, mapOf("key" to "value")),
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_3, mapOf("key" to "value")),
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_4, mapOf("key" to "value")),
|
||||||
|
)
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.givenGetUserAccountDataEventsStartWith(
|
||||||
|
type = MATRIX_CLIENT_INFO_KEY_PREFIX,
|
||||||
|
userAccountDataEventList = userAccountDataEventList,
|
||||||
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
|
deleteUnusedClientInformationUseCase.execute(devices)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
coVerify { fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.deleteUserAccountData(MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_3) }
|
||||||
|
coVerify { fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.deleteUserAccountData(MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_4) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a device list that account data has exactly all of them then use case does nothing`() = runTest {
|
||||||
|
// Given
|
||||||
|
val devices = listOf(A_DEVICE_INFO_1, A_DEVICE_INFO_2)
|
||||||
|
val userAccountDataEventList = listOf(
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_1, mapOf("key" to "value")),
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_2, mapOf("key" to "value")),
|
||||||
|
)
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.givenGetUserAccountDataEventsStartWith(
|
||||||
|
type = MATRIX_CLIENT_INFO_KEY_PREFIX,
|
||||||
|
userAccountDataEventList = userAccountDataEventList,
|
||||||
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
|
deleteUnusedClientInformationUseCase.execute(devices)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.deleteUserAccountData(any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a device list that account data has missing some of them then use case does nothing`() = runTest {
|
||||||
|
// Given
|
||||||
|
val devices = listOf(A_DEVICE_INFO_1, A_DEVICE_INFO_2)
|
||||||
|
val userAccountDataEventList = listOf(
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_1, mapOf("key" to "value")),
|
||||||
|
)
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.givenGetUserAccountDataEventsStartWith(
|
||||||
|
type = MATRIX_CLIENT_INFO_KEY_PREFIX,
|
||||||
|
userAccountDataEventList = userAccountDataEventList,
|
||||||
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
|
deleteUnusedClientInformationUseCase.execute(devices)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.deleteUserAccountData(any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given an empty device list that account data has some devices then use case does nothing`() = runTest {
|
||||||
|
// Given
|
||||||
|
val devices = emptyList<DeviceInfo>()
|
||||||
|
val userAccountDataEventList = listOf(
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_1, mapOf("key" to "value")),
|
||||||
|
UserAccountDataEvent(type = MATRIX_CLIENT_INFO_KEY_PREFIX + A_DEVICE_ID_2, mapOf("key" to "value")),
|
||||||
|
)
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.givenGetUserAccountDataEventsStartWith(
|
||||||
|
type = MATRIX_CLIENT_INFO_KEY_PREFIX,
|
||||||
|
userAccountDataEventList = userAccountDataEventList,
|
||||||
|
)
|
||||||
|
|
||||||
|
// When
|
||||||
|
deleteUnusedClientInformationUseCase.execute(devices)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
coVerify(exactly = 0) {
|
||||||
|
fakeActiveSessionHolder.fakeSession.fakeSessionAccountDataService.deleteUserAccountData(any())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,4 +54,8 @@ class FakeSessionAccountDataService : SessionAccountDataService by mockk(relaxed
|
||||||
fun verifyUpdateUserAccountDataEventSucceeds(type: String, content: Content, inverse: Boolean = false) {
|
fun verifyUpdateUserAccountDataEventSucceeds(type: String, content: Content, inverse: Boolean = false) {
|
||||||
coVerify(inverse = inverse) { updateUserAccountData(type, content) }
|
coVerify(inverse = inverse) { updateUserAccountData(type, content) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun givenGetUserAccountDataEventsStartWith(type: String, userAccountDataEventList: List<UserAccountDataEvent>) {
|
||||||
|
every { getUserAccountDataEventsStartWith(type) } returns userAccountDataEventList
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue