From 69720ffdd3914e02b43ed3bddc26637dc8c59fd6 Mon Sep 17 00:00:00 2001 From: ganfra Date: Fri, 19 Nov 2021 17:18:39 +0100 Subject: [PATCH] Android tests: introduce TestBackgroundDetectionObserver so sync is not cancelled while testing + fix small warnings --- .../sdk/api/{Matrix.kt => TestMatrix.kt} | 23 +++++----- .../android/sdk/common/CommonTestHelper.kt | 12 +++-- .../android/sdk/common/TestMatrixComponent.kt | 6 ++- .../matrix/android/sdk/common/TestModule.kt | 33 ++++++++++++++ .../android/sdk/common/TestNetworkModule.kt | 39 ---------------- .../session/room/timeline/RoomDataHelper.kt | 4 +- .../sdk/session/space/SpaceHierarchyTest.kt | 1 + .../util/BackgroundDetectionObserver.kt | 45 +++++++++++++------ .../im/vector/app/SecurityBootstrapTest.kt | 3 +- .../im/vector/app/VerificationTestBase.kt | 4 +- .../app/VerifySessionInteractiveTest.kt | 3 +- .../vector/app/VerifySessionPassphraseTest.kt | 3 +- 12 files changed, 97 insertions(+), 79 deletions(-) rename matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/{Matrix.kt => TestMatrix.kt} (83%) delete mode 100644 matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestNetworkModule.kt diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/TestMatrix.kt similarity index 83% rename from matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt rename to matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/TestMatrix.kt index 8b9b6efa11..4c7a77b208 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/api/TestMatrix.kt @@ -35,16 +35,16 @@ import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.network.ApiInterceptor import org.matrix.android.sdk.internal.network.UserAgentHolder import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver +import org.matrix.android.sdk.internal.worker.MatrixWorkerFactory import org.matrix.olm.OlmManager import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject /** - * This is the main entry point to the matrix sdk. - * To get the singleton instance, use getInstance static method. + * This mimics the Matrix class but using TestMatrixComponent internally instead of regular MatrixComponent. */ -class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) { +class TestMatrix constructor(context: Context, matrixConfiguration: MatrixConfiguration) { @Inject internal lateinit var legacySessionImporter: LegacySessionImporter @Inject internal lateinit var authenticationService: AuthenticationService @@ -55,15 +55,18 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo @Inject internal lateinit var sessionManager: SessionManager @Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService @Inject internal lateinit var apiInterceptor: ApiInterceptor + @Inject internal lateinit var matrixWorkerFactory: MatrixWorkerFactory private val uiHandler = Handler(Looper.getMainLooper()) init { Monarchy.init(context) DaggerTestMatrixComponent.factory().create(context, matrixConfiguration).inject(this) - if (context.applicationContext !is Configuration.Provider) { - WorkManager.initialize(context, Configuration.Builder().setExecutor(Executors.newCachedThreadPool()).build()) - } + val configuration = Configuration.Builder() + .setExecutor(Executors.newCachedThreadPool()) + .setWorkerFactory(matrixWorkerFactory) + .build() + WorkManager.initialize(context, configuration) uiHandler.post { ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver) } @@ -93,21 +96,21 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo companion object { - private lateinit var instance: Matrix + private lateinit var instance: TestMatrix private val isInit = AtomicBoolean(false) fun initialize(context: Context, matrixConfiguration: MatrixConfiguration) { if (isInit.compareAndSet(false, true)) { - instance = Matrix(context.applicationContext, matrixConfiguration) + instance = TestMatrix(context.applicationContext, matrixConfiguration) } } - fun getInstance(context: Context): Matrix { + fun getInstance(context: Context): TestMatrix { if (isInit.compareAndSet(false, true)) { val appContext = context.applicationContext if (appContext is MatrixConfiguration.Provider) { val matrixConfiguration = (appContext as MatrixConfiguration.Provider).providesMatrixConfiguration() - instance = Matrix(appContext, matrixConfiguration) + instance = TestMatrix(appContext, matrixConfiguration) } else { throw IllegalStateException("Matrix is not initialized properly." + " You should call Matrix.initialize or let your application implements MatrixConfiguration.Provider.") diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index cf9b8f87c1..8f81c79129 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -20,7 +20,6 @@ import android.content.Context import android.net.Uri import androidx.lifecycle.Observer import androidx.test.internal.runner.junit4.statement.UiThreadStatement -import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiThread import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay @@ -30,9 +29,9 @@ import kotlinx.coroutines.withTimeout import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue -import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixConfiguration +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.registration.RegistrationResult import org.matrix.android.sdk.api.session.Session @@ -45,7 +44,6 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.api.session.sync.SyncState -import java.util.ArrayList import java.util.UUID import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -56,13 +54,13 @@ import java.util.concurrent.TimeUnit */ class CommonTestHelper(context: Context) { - val matrix: Matrix + val matrix: TestMatrix - fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestNetworkModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor + fun getTestInterceptor(session: Session): MockOkHttpInterceptor? = TestModule.interceptorForSession(session.sessionId) as? MockOkHttpInterceptor init { UiThreadStatement.runOnUiThread { - Matrix.initialize( + TestMatrix.initialize( context, MatrixConfiguration( applicationFlavor = "TestFlavor", @@ -70,7 +68,7 @@ class CommonTestHelper(context: Context) { ) ) } - matrix = Matrix.getInstance(context) + matrix = TestMatrix.getInstance(context) } fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt index 1d05e655af..ca4d81d0b8 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt @@ -20,6 +20,7 @@ import android.content.Context import dagger.BindsInstance import dagger.Component import org.matrix.android.sdk.api.MatrixConfiguration +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.internal.auth.AuthModule import org.matrix.android.sdk.internal.di.MatrixComponent import org.matrix.android.sdk.internal.di.MatrixModule @@ -34,12 +35,13 @@ import org.matrix.android.sdk.internal.util.system.SystemModule NetworkModule::class, AuthModule::class, RawModule::class, - SystemModule::class, - TestNetworkModule::class + SystemModule::class ]) @MatrixScope internal interface TestMatrixComponent : MatrixComponent { + fun inject(matrix: TestMatrix) + @Component.Factory interface Factory { fun create(@BindsInstance context: Context, diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestModule.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestModule.kt index 3e4d5fe08e..51b3a1f4da 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestModule.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestModule.kt @@ -18,10 +18,43 @@ package org.matrix.android.sdk.common import dagger.Binds import dagger.Module +import dagger.Provides import org.matrix.android.sdk.internal.di.MatrixComponent +import org.matrix.android.sdk.internal.di.MatrixScope +import org.matrix.android.sdk.internal.session.MockHttpInterceptor +import org.matrix.android.sdk.internal.session.TestInterceptor +import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver +import org.matrix.android.sdk.internal.util.DefaultBackgroundDetectionObserver +import org.matrix.android.sdk.internal.util.TestBackgroundDetectionObserver @Module internal abstract class TestModule { @Binds abstract fun providesMatrixComponent(testMatrixComponent: TestMatrixComponent): MatrixComponent + + @Module + companion object { + + val interceptors = ArrayList() + + fun interceptorForSession(sessionId: String): TestInterceptor? = interceptors.firstOrNull { it.sessionId == sessionId } + + @Provides + @JvmStatic + @MockHttpInterceptor + fun providesTestInterceptor(): TestInterceptor? { + return MockOkHttpInterceptor().also { + interceptors.add(it) + } + } + + @Provides + @JvmStatic + @MatrixScope + fun providesBackgroundDetectionObserver(): BackgroundDetectionObserver { + return TestBackgroundDetectionObserver() + } + + } + } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestNetworkModule.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestNetworkModule.kt deleted file mode 100644 index 4cd92ca272..0000000000 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestNetworkModule.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020 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.common - -import dagger.Module -import dagger.Provides -import org.matrix.android.sdk.internal.session.MockHttpInterceptor -import org.matrix.android.sdk.internal.session.TestInterceptor - -@Module -internal object TestNetworkModule { - - val interceptors = ArrayList() - - fun interceptorForSession(sessionId: String): TestInterceptor? = interceptors.firstOrNull { it.sessionId == sessionId } - - @Provides - @JvmStatic - @MockHttpInterceptor - fun providesTestInterceptor(): TestInterceptor? { - return MockOkHttpInterceptor().also { - interceptors.add(it) - } - } -} diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt index 1adf31be5f..0bbec7ac13 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/room/timeline/RoomDataHelper.kt @@ -45,7 +45,7 @@ object RoomDataHelper { content: Content? = null, prevContent: Content? = null, sender: String = FAKE_TEST_SENDER, - stateKey: String = FAKE_TEST_SENDER + stateKey: String? =null ): Event { return Event( type = type, @@ -64,6 +64,6 @@ object RoomDataHelper { private fun createFakeRoomMemberEvent(): Event { val roomMember = RoomMemberContent(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent() - return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember) + return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember, stateKey = FAKE_TEST_SENDER) } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt index 436daf001b..09b0daf898 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/session/space/SpaceHierarchyTest.kt @@ -540,6 +540,7 @@ class SpaceHierarchyTest : InstrumentedTest { } @Test + @Suppress("EXPERIMENTAL_API_USAGE") fun testParentRelation() { val aliceSession = commonTestHelper.createAccount("Alice", SessionTestParams(true)) val bobSession = commonTestHelper.createAccount("Bib", SessionTestParams(true)) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt index 3e977b31fb..c4f059fe78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt @@ -22,22 +22,31 @@ import org.matrix.android.sdk.internal.di.MatrixScope import timber.log.Timber import javax.inject.Inject -/** - * To be attached to ProcessLifecycleOwner lifecycle - */ -@MatrixScope -internal class BackgroundDetectionObserver @Inject constructor() : DefaultLifecycleObserver { - var isInBackground: Boolean = true +interface BackgroundDetectionObserver: DefaultLifecycleObserver { + val isInBackground: Boolean + + fun register(listener: Listener) + fun unregister(listener: Listener) + + interface Listener { + fun onMoveToForeground() + fun onMoveToBackground() + } +} + +internal class DefaultBackgroundDetectionObserver: BackgroundDetectionObserver { + + override var isInBackground: Boolean = true private set - private val listeners = LinkedHashSet() + private val listeners = LinkedHashSet() - fun register(listener: Listener) { + override fun register(listener: BackgroundDetectionObserver.Listener) { listeners.add(listener) } - fun unregister(listener: Listener) { + override fun unregister(listener: BackgroundDetectionObserver.Listener) { listeners.remove(listener) } @@ -52,9 +61,17 @@ internal class BackgroundDetectionObserver @Inject constructor() : DefaultLifecy isInBackground = true listeners.forEach { it.onMoveToBackground() } } - - interface Listener { - fun onMoveToForeground() - fun onMoveToBackground() - } +} + +/** + * Force foreground for testing + */ +internal class TestBackgroundDetectionObserver : BackgroundDetectionObserver { + + override val isInBackground: Boolean = false + + override fun register(listener: BackgroundDetectionObserver.Listener) = Unit + + override fun unregister(listener: BackgroundDetectionObserver.Listener) = Unit + } diff --git a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt index 0d0ec3dd2b..fb3180e624 100644 --- a/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt +++ b/vector/src/androidTest/java/im/vector/app/SecurityBootstrapTest.kt @@ -48,6 +48,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.matrix.android.sdk.api.Matrix +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.api.session.Session @RunWith(AndroidJUnit4::class) @@ -62,7 +63,7 @@ class SecurityBootstrapTest : VerificationTestBase() { @Before fun createSessionWithCrossSigning() { val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = TestMatrix.getInstance(context) val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) stubAllExternalIntents() diff --git a/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt b/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt index 47e1e43be3..df3066cd3b 100644 --- a/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt +++ b/vector/src/androidTest/java/im/vector/app/VerificationTestBase.kt @@ -25,8 +25,8 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withTimeout import org.junit.Assert -import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.MatrixCallback +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.registration.RegistrationResult import org.matrix.android.sdk.api.session.Session @@ -41,7 +41,7 @@ abstract class VerificationTestBase { protected val uiTestBase = OnboardingRobot() - fun createAccountAndSync(matrix: Matrix, + fun createAccountAndSync(matrix: TestMatrix, userName: String, password: String, withInitialSync: Boolean): Session { diff --git a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt index 982a421425..69814759a2 100644 --- a/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt +++ b/vector/src/androidTest/java/im/vector/app/VerifySessionInteractiveTest.kt @@ -42,6 +42,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.matrix.android.sdk.api.Matrix +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth @@ -67,7 +68,7 @@ class VerifySessionInteractiveTest : VerificationTestBase() { @Before fun createSessionWithCrossSigning() { val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = TestMatrix.getInstance(context) val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) doSync { diff --git a/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt b/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt index c51ff29669..8c6d8b56dc 100644 --- a/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt +++ b/vector/src/androidTest/java/im/vector/app/VerifySessionPassphraseTest.kt @@ -46,6 +46,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.matrix.android.sdk.api.Matrix +import org.matrix.android.sdk.api.TestMatrix import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth @@ -67,7 +68,7 @@ class VerifySessionPassphraseTest : VerificationTestBase() { @Before fun createSessionWithCrossSigningAnd4S() { val context = InstrumentationRegistry.getInstrumentation().targetContext - val matrix = Matrix.getInstance(context) + val matrix = TestMatrix.getInstance(context) val userName = "foobar_${System.currentTimeMillis()}" existingSession = createAccountAndSync(matrix, userName, password, true) doSync {