Refactor: Move InMemorySessionStore to test module (#5252)

* Refactor: Move InMemorySessionStore to test module

- Delete `libraries/session-storage/impl-memory` module
- Move `InMemorySessionStore.kt` to `libraries/session-storage/test`

* Cleanup tests.

* Fix error.
This commit is contained in:
Benoit Marty 2025-09-01 17:29:43 +02:00 committed by GitHub
commit 00ca73f342
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 144 additions and 188 deletions

View file

@ -48,7 +48,6 @@ dependencies {
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)
testImplementation(projects.services.toolbox.test)

View file

@ -10,7 +10,7 @@ package io.element.android.libraries.matrix.impl
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSession
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -23,11 +23,12 @@ import org.junit.Test
class RustClientSessionDelegateTest {
@Test
fun `saveSessionInKeychain should update the store`() = runTest {
val sessionStore = InMemorySessionStore()
sessionStore.storeData(
aSessionData(
accessToken = "anAccessToken",
refreshToken = "aRefreshToken",
val sessionStore = InMemorySessionStore(
initialList = listOf(
aSessionData(
accessToken = "anAccessToken",
refreshToken = "aRefreshToken",
)
)
)
val sut = aRustClientSessionDelegate(sessionStore)

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvide
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.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

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilter
import io.element.android.libraries.matrix.test.A_DEVICE_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.testCoroutineDispatchers

View file

@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory
import io.element.android.libraries.matrix.test.auth.FakeOidcRedirectUrlProvider
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.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.testCoroutineDispatchers
import kotlinx.coroutines.test.TestScope

View file

@ -9,7 +9,7 @@ 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.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import kotlinx.coroutines.test.runTest
import org.junit.Test
@ -24,14 +24,15 @@ class SessionPathsProviderTest {
@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 store = InMemorySessionStore(
initialList = listOf(
aSessionData(
sessionPath = "/a/path/to/a/session",
cachePath = "/a/path/to/a/cache",
)
)
)
val sut = SessionPathsProvider(store)
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")

View file

@ -79,7 +79,6 @@ dependencies {
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.libraries.push.test)
testImplementation(projects.libraries.pushstore.test)
testImplementation(projects.libraries.sessionStorage.implMemory)
testImplementation(projects.libraries.sessionStorage.test)
testImplementation(projects.tests.testutils)
testImplementation(projects.services.toolbox.test)

View file

@ -22,8 +22,7 @@ import io.element.android.libraries.pushstore.api.UserPushStoreFactory
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStore
import io.element.android.libraries.pushstore.test.userpushstore.FakeUserPushStoreFactory
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemoryMultiSessionsStore
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.libraries.sessionstorage.test.aSessionData
import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
@ -50,11 +49,13 @@ class DefaultFirebaseNewTokenHandlerTest {
val registerPusherResult = lambdaRecorder<MatrixClient, String, String, Result<Unit>> { _, _, _ -> Result.success(Unit) }
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID.value))
storeData(aSessionData(A_USER_ID_2.value))
storeData(aSessionData(A_USER_ID_3.value))
},
sessionStore = InMemorySessionStore(
initialList = listOf(
aSessionData(A_USER_ID.value),
aSessionData(A_USER_ID_2.value),
aSessionData(A_USER_ID_3.value),
)
),
matrixClientProvider = FakeMatrixClientProvider { sessionId ->
when (sessionId) {
A_USER_ID -> Result.success(aMatrixClient1)
@ -89,9 +90,9 @@ class DefaultFirebaseNewTokenHandlerTest {
val registerPusherResult = lambdaRecorder<MatrixClient, String, String, Result<Unit>> { _, _, _ -> Result.success(Unit) }
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID.value))
},
sessionStore = InMemorySessionStore(
initialList = listOf(aSessionData(A_USER_ID.value))
),
matrixClientProvider = FakeMatrixClientProvider {
Result.failure(IllegalStateException())
},
@ -113,9 +114,9 @@ class DefaultFirebaseNewTokenHandlerTest {
val registerPusherResult = lambdaRecorder<MatrixClient, String, String, Result<Unit>> { _, _, _ -> Result.failure(AN_EXCEPTION) }
val pusherSubscriber = FakePusherSubscriber(registerPusherResult = registerPusherResult)
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
sessionStore = InMemoryMultiSessionsStore().apply {
storeData(aSessionData(A_USER_ID.value))
},
sessionStore = InMemorySessionStore(
initialList = listOf(aSessionData(A_USER_ID.value))
),
matrixClientProvider = FakeMatrixClientProvider {
Result.success(aMatrixClient1)
},

View file

@ -1,18 +0,0 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.libraries.sessionstorage.impl.memory"
}
dependencies {
implementation(projects.libraries.sessionStorage.api)
implementation(libs.coroutines.core)
}

View file

@ -1,35 +0,0 @@
/*
* Copyright 2023, 2024 New Vector 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.sessionstorage.impl.memory
import io.element.android.libraries.sessionstorage.api.LoggedInState
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.Flow
class InMemoryMultiSessionsStore : SessionStore {
private val sessions = mutableListOf<SessionData>()
override fun isLoggedIn(): Flow<LoggedInState> = error("Not implemented")
override fun sessionsFlow(): Flow<List<SessionData>> = error("Not implemented")
override suspend fun storeData(sessionData: SessionData) {
sessions.add(sessionData)
}
override suspend fun updateData(sessionData: SessionData) = error("Not implemented")
override suspend fun getSession(sessionId: String): SessionData? = error("Not implemented")
override suspend fun getAllSessions(): List<SessionData> = sessions
override suspend fun getLatestSession(): SessionData = error("Not implemented")
override suspend fun removeSession(sessionId: String) = error("Not implemented")
}

View file

@ -1,62 +0,0 @@
/*
* Copyright 2023, 2024 New Vector 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.sessionstorage.impl.memory
import io.element.android.libraries.sessionstorage.api.LoggedInState
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map
class InMemorySessionStore : SessionStore {
private var sessionDataFlow = MutableStateFlow<SessionData?>(null)
override fun isLoggedIn(): Flow<LoggedInState> {
return sessionDataFlow.map {
if (it == null) {
LoggedInState.NotLoggedIn
} else {
LoggedInState.LoggedIn(
sessionId = it.userId,
isTokenValid = it.isTokenValid,
)
}
}
}
override fun sessionsFlow(): Flow<List<SessionData>> {
return sessionDataFlow.map { listOfNotNull(it) }
}
override suspend fun storeData(sessionData: SessionData) {
sessionDataFlow.value = sessionData
}
override suspend fun updateData(sessionData: SessionData) {
sessionDataFlow.value = sessionData
}
override suspend fun getSession(sessionId: String): SessionData? {
return sessionDataFlow.value.takeIf { it?.userId == sessionId }
}
override suspend fun getAllSessions(): List<SessionData> {
return listOfNotNull(sessionDataFlow.value)
}
override suspend fun getLatestSession(): SessionData? {
return sessionDataFlow.value
}
override suspend fun removeSession(sessionId: String) {
if (sessionDataFlow.value?.userId == sessionId) {
sessionDataFlow.value = null
}
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright 2023, 2024 New Vector 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.sessionstorage.test
import io.element.android.libraries.sessionstorage.api.LoggedInState
import io.element.android.libraries.sessionstorage.api.SessionData
import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
class InMemorySessionStore(
initialList: List<SessionData> = emptyList(),
) : SessionStore {
private val sessionDataListFlow = MutableStateFlow(initialList)
override fun isLoggedIn(): Flow<LoggedInState> {
return sessionDataListFlow.map {
if (it.isEmpty()) {
LoggedInState.NotLoggedIn
} else {
it.first().let { sessionData ->
LoggedInState.LoggedIn(
sessionId = sessionData.userId,
isTokenValid = sessionData.isTokenValid,
)
}
}
}
}
override fun sessionsFlow(): Flow<List<SessionData>> = sessionDataListFlow.asStateFlow()
override suspend fun storeData(sessionData: SessionData) {
val currentList = sessionDataListFlow.value.toMutableList()
currentList.removeAll { it.userId == sessionData.userId }
currentList.add(sessionData)
sessionDataListFlow.value = currentList
}
override suspend fun updateData(sessionData: SessionData) {
val currentList = sessionDataListFlow.value.toMutableList()
val index = currentList.indexOfFirst { it.userId == sessionData.userId }
if (index != -1) {
currentList[index] = sessionData
sessionDataListFlow.value = currentList
}
}
override suspend fun getSession(sessionId: String): SessionData? {
return sessionDataListFlow.value.firstOrNull { it.userId == sessionId }
}
override suspend fun getAllSessions(): List<SessionData> {
return sessionDataListFlow.value
}
override suspend fun getLatestSession(): SessionData? {
return sessionDataListFlow.value.firstOrNull()
}
override suspend fun removeSession(sessionId: String) {
val currentList = sessionDataListFlow.value.toMutableList()
currentList.removeAll { it.userId == sessionId }
sessionDataListFlow.value = currentList
}
}