Add test on DefaultFirebaseNewTokenHandler
This commit is contained in:
@@ -31,7 +31,9 @@ import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
val A_OIDC_DATA = OidcDetails(url = "a-url")
|
||||
|
||||
class FakeAuthenticationService : MatrixAuthenticationService {
|
||||
class FakeAuthenticationService(
|
||||
private val matrixClientResult: ((SessionId) -> Result<MatrixClient>)? = null
|
||||
) : MatrixAuthenticationService {
|
||||
private val homeserver = MutableStateFlow<MatrixHomeServerDetails?>(null)
|
||||
private var oidcError: Throwable? = null
|
||||
private var oidcCancelError: Throwable? = null
|
||||
@@ -48,6 +50,9 @@ class FakeAuthenticationService : MatrixAuthenticationService {
|
||||
override suspend fun getLatestSessionId(): SessionId? = getLatestSessionIdLambda()
|
||||
|
||||
override suspend fun restoreSession(sessionId: SessionId): Result<MatrixClient> {
|
||||
if (matrixClientResult != null) {
|
||||
return matrixClientResult.invoke(sessionId)
|
||||
}
|
||||
return if (matrixClient != null) {
|
||||
Result.success(matrixClient!!)
|
||||
} else {
|
||||
|
||||
@@ -60,14 +60,15 @@ class DefaultFirebaseNewTokenHandler @Inject constructor(
|
||||
Timber.tag(loggerTag.value).e(it, "Failed to restore session $sessionId")
|
||||
}
|
||||
.flatMap { client ->
|
||||
pusherSubscriber.registerPusher(
|
||||
matrixClient = client,
|
||||
pushKey = firebaseToken,
|
||||
gateway = FirebaseConfig.PUSHER_HTTP_URL,
|
||||
)
|
||||
}
|
||||
.onFailure {
|
||||
Timber.tag(loggerTag.value).e(it, "Failed to register pusher for session $sessionId")
|
||||
pusherSubscriber
|
||||
.registerPusher(
|
||||
matrixClient = client,
|
||||
pushKey = firebaseToken,
|
||||
gateway = FirebaseConfig.PUSHER_HTTP_URL,
|
||||
)
|
||||
.onFailure {
|
||||
Timber.tag(loggerTag.value).e(it, "Failed to register pusher for session $sessionId")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Timber.tag(loggerTag.value).d("This session is not using Firebase pusher")
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 io.element.android.libraries.pushproviders.firebase
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_2
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID_3
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.auth.FakeAuthenticationService
|
||||
import io.element.android.libraries.push.test.FakePusherSubscriber
|
||||
import io.element.android.libraries.pushproviders.api.PusherSubscriber
|
||||
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.LoginType
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
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.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class DefaultFirebaseNewTokenHandlerTest {
|
||||
@Test
|
||||
fun `when a new token is received it is stored in the firebase store`() = runTest {
|
||||
val firebaseStore = InMemoryFirebaseStore()
|
||||
assertThat(firebaseStore.getFcmToken()).isNull()
|
||||
val firebaseNewTokenHandler = createDefaultFirebaseNewTokenHandler(
|
||||
firebaseStore = firebaseStore,
|
||||
)
|
||||
firebaseNewTokenHandler.handle("aToken")
|
||||
assertThat(firebaseStore.getFcmToken()).isEqualTo("aToken")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a new token is received, the handler registers the pusher again to all sessions using Firebase`() = runTest {
|
||||
val aMatrixClient1 = FakeMatrixClient(A_USER_ID)
|
||||
val aMatrixClient2 = FakeMatrixClient(A_USER_ID_2)
|
||||
val aMatrixClient3 = FakeMatrixClient(A_USER_ID_3)
|
||||
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))
|
||||
storeData(aSessionData(A_USER_ID_2))
|
||||
storeData(aSessionData(A_USER_ID_3))
|
||||
},
|
||||
matrixAuthenticationService = FakeAuthenticationService(
|
||||
matrixClientResult = { sessionId ->
|
||||
when (sessionId) {
|
||||
A_USER_ID -> Result.success(aMatrixClient1)
|
||||
A_USER_ID_2 -> Result.success(aMatrixClient2)
|
||||
A_USER_ID_3 -> Result.success(aMatrixClient3)
|
||||
else -> Result.failure(IllegalStateException())
|
||||
}
|
||||
}
|
||||
),
|
||||
userPushStoreFactory = FakeUserPushStoreFactory(
|
||||
userPushStore = { sessionId ->
|
||||
when (sessionId) {
|
||||
A_USER_ID -> FakeUserPushStore(pushProviderName = FirebaseConfig.NAME)
|
||||
A_USER_ID_2 -> FakeUserPushStore(pushProviderName = "Other")
|
||||
A_USER_ID_3 -> FakeUserPushStore(pushProviderName = FirebaseConfig.NAME)
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
}
|
||||
),
|
||||
pusherSubscriber = pusherSubscriber,
|
||||
)
|
||||
firebaseNewTokenHandler.handle("aToken")
|
||||
registerPusherResult.assertions()
|
||||
.isCalledExactly(2)
|
||||
.withSequence(
|
||||
listOf(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
|
||||
listOf(value(aMatrixClient3), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL)),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a new token is received, if the session cannot be restore, nothing happen`() = runTest {
|
||||
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))
|
||||
},
|
||||
matrixAuthenticationService = FakeAuthenticationService(
|
||||
matrixClientResult = { _ ->
|
||||
Result.failure(IllegalStateException())
|
||||
}
|
||||
),
|
||||
userPushStoreFactory = FakeUserPushStoreFactory(
|
||||
userPushStore = { _ ->
|
||||
FakeUserPushStore(pushProviderName = FirebaseConfig.NAME)
|
||||
}
|
||||
),
|
||||
pusherSubscriber = pusherSubscriber,
|
||||
)
|
||||
firebaseNewTokenHandler.handle("aToken")
|
||||
registerPusherResult.assertions()
|
||||
.isNeverCalled()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when a new token is received, error when registering the pusher is ignored`() = runTest {
|
||||
val aMatrixClient1 = FakeMatrixClient(A_USER_ID)
|
||||
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))
|
||||
},
|
||||
matrixAuthenticationService = FakeAuthenticationService(
|
||||
matrixClientResult = { _ ->
|
||||
Result.success(aMatrixClient1)
|
||||
}
|
||||
),
|
||||
userPushStoreFactory = FakeUserPushStoreFactory(
|
||||
userPushStore = { _ ->
|
||||
FakeUserPushStore(pushProviderName = FirebaseConfig.NAME)
|
||||
}
|
||||
),
|
||||
pusherSubscriber = pusherSubscriber,
|
||||
)
|
||||
firebaseNewTokenHandler.handle("aToken")
|
||||
registerPusherResult.assertions()
|
||||
registerPusherResult.assertions()
|
||||
.isCalledOnce()
|
||||
.with(value(aMatrixClient1), value("aToken"), value(FirebaseConfig.PUSHER_HTTP_URL))
|
||||
}
|
||||
|
||||
private fun createDefaultFirebaseNewTokenHandler(
|
||||
pusherSubscriber: PusherSubscriber = FakePusherSubscriber(),
|
||||
sessionStore: SessionStore = InMemorySessionStore(),
|
||||
userPushStoreFactory: UserPushStoreFactory = FakeUserPushStoreFactory(),
|
||||
matrixAuthenticationService: MatrixAuthenticationService = FakeAuthenticationService(),
|
||||
firebaseStore: FirebaseStore = InMemoryFirebaseStore(),
|
||||
): FirebaseNewTokenHandler {
|
||||
return DefaultFirebaseNewTokenHandler(
|
||||
pusherSubscriber = pusherSubscriber,
|
||||
sessionStore = sessionStore,
|
||||
userPushStoreFactory = userPushStoreFactory,
|
||||
matrixAuthenticationService = matrixAuthenticationService,
|
||||
firebaseStore = firebaseStore
|
||||
)
|
||||
}
|
||||
|
||||
private fun aSessionData(
|
||||
sessionId: SessionId,
|
||||
): SessionData {
|
||||
return SessionData(
|
||||
userId = sessionId.value,
|
||||
deviceId = "aDeviceId",
|
||||
accessToken = "anAccessToken",
|
||||
refreshToken = "aRefreshToken",
|
||||
homeserverUrl = "aHomeserverUrl",
|
||||
oidcData = null,
|
||||
slidingSyncProxy = null,
|
||||
loginTimestamp = null,
|
||||
isTokenValid = true,
|
||||
loginType = LoginType.UNKNOWN,
|
||||
passphrase = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,9 @@ import io.element.android.libraries.pushstore.api.UserPushStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeUserPushStore : UserPushStore {
|
||||
class FakeUserPushStore(
|
||||
private var pushProviderName: String? = null
|
||||
) : UserPushStore {
|
||||
private var currentRegisteredPushKey: String? = null
|
||||
private val notificationEnabledForDevice = MutableStateFlow(true)
|
||||
override suspend fun getPushProviderName(): String? {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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 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")
|
||||
}
|
||||
Reference in New Issue
Block a user