diff options
| -rw-r--r-- | packages/SettingsLib/Ipc/Android.bp | 12 | ||||
| -rw-r--r-- | packages/SettingsLib/Ipc/testutils/com/android/settingslib/ipc/MessengerServiceRule.kt | 79 |
2 files changed, 91 insertions, 0 deletions
diff --git a/packages/SettingsLib/Ipc/Android.bp b/packages/SettingsLib/Ipc/Android.bp index 61adb46b44e3..2c7209a48bbd 100644 --- a/packages/SettingsLib/Ipc/Android.bp +++ b/packages/SettingsLib/Ipc/Android.bp @@ -20,3 +20,15 @@ android_library { ], kotlincflags: ["-Xjvm-default=all"], } + +android_library { + name: "SettingsLibIpc-testutils", + srcs: ["testutils/**/*.kt"], + static_libs: [ + "Robolectric_all-target_upstream", + "SettingsLibIpc", + "androidx.test.core", + "flag-junit", + "kotlinx-coroutines-android", + ], +} diff --git a/packages/SettingsLib/Ipc/testutils/com/android/settingslib/ipc/MessengerServiceRule.kt b/packages/SettingsLib/Ipc/testutils/com/android/settingslib/ipc/MessengerServiceRule.kt new file mode 100644 index 000000000000..8b2deaf68786 --- /dev/null +++ b/packages/SettingsLib/Ipc/testutils/com/android/settingslib/ipc/MessengerServiceRule.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * 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 com.android.settingslib.ipc + +import android.app.Application +import android.app.Service +import android.content.ComponentName +import android.content.Intent +import android.os.Build +import android.os.Looper +import androidx.test.core.app.ApplicationProvider +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withContext +import org.junit.rules.TestWatcher +import org.junit.runner.Description +import org.robolectric.Robolectric +import org.robolectric.Shadows +import org.robolectric.android.controller.ServiceController + +/** Rule for messenger service testing. */ +open class MessengerServiceRule<C : MessengerServiceClient>( + private val serviceClass: Class<out MessengerService>, + val client: C, +) : TestWatcher() { + val application: Application = ApplicationProvider.getApplicationContext() + val isRobolectric = Build.FINGERPRINT.contains("robolectric") + + private var serviceController: ServiceController<out Service>? = null + + override fun starting(description: Description) { + if (isRobolectric) { + runBlocking { setupRobolectricService() } + } + } + + override fun finished(description: Description) { + client.close() + if (isRobolectric) { + runBlocking { + withContext(Dispatchers.Main) { serviceController?.run { unbind().destroy() } } + } + } + } + + private suspend fun setupRobolectricService() { + if (Thread.currentThread() == Looper.getMainLooper().thread) { + throw IllegalStateException( + "To avoid deadlock, run test with @LooperMode(LooperMode.Mode.INSTRUMENTATION_TEST)" + ) + } + withContext(Dispatchers.Main) { + serviceController = Robolectric.buildService(serviceClass) + val service = serviceController!!.create().get() + Shadows.shadowOf(application).apply { + setComponentNameAndServiceForBindService( + ComponentName(application, serviceClass), + service.onBind(Intent(application, serviceClass)), + ) + setBindServiceCallsOnServiceConnectedDirectly(true) + setUnbindServiceCallsOnServiceDisconnected(false) + } + } + } +} |