Merge changes Ia3b1ae8f,Ie87220a7 into tm-qpr-dev am: 52c7bc24e2
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20562448 Change-Id: I655ecdff4f09577244a6672b6a30c6ef58f87bf1 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
committed by
Automerger Merge Worker
commit
b28ae70b2b
@@ -41,6 +41,7 @@ import com.android.systemui.util.mockito.eq
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.nullable
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -55,7 +56,7 @@ class FooterActionsInteractorTest : SysuiTestCase() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
utils = FooterActionsTestUtils(context, TestableLooper.get(this))
|
||||
utils = FooterActionsTestUtils(context, TestableLooper.get(this), TestCoroutineScheduler())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
import com.android.systemui.common.shared.model.ContentDescription
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.coroutines.collectLastValue
|
||||
import com.android.systemui.qs.FakeFgsManagerController
|
||||
import com.android.systemui.qs.QSSecurityFooterUtils
|
||||
import com.android.systemui.qs.footer.FooterActionsTestUtils
|
||||
@@ -44,12 +45,9 @@ import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.nullable
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
@@ -62,16 +60,20 @@ import org.mockito.Mockito.`when` as whenever
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper
|
||||
class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
private val testScope = TestScope()
|
||||
private lateinit var utils: FooterActionsTestUtils
|
||||
private val testDispatcher = UnconfinedTestDispatcher(TestCoroutineScheduler())
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
utils = FooterActionsTestUtils(context, TestableLooper.get(this))
|
||||
utils = FooterActionsTestUtils(context, TestableLooper.get(this), testScope.testScheduler)
|
||||
}
|
||||
|
||||
private fun runTest(block: suspend TestScope.() -> Unit) {
|
||||
testScope.runTest(testBody = block)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun settingsButton() = runBlockingTest {
|
||||
fun settingsButton() = runTest {
|
||||
val underTest = utils.footerActionsViewModel(showPowerButton = false)
|
||||
val settings = underTest.settings
|
||||
|
||||
@@ -87,7 +89,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun powerButton() = runBlockingTest {
|
||||
fun powerButton() = runTest {
|
||||
// Without power button.
|
||||
val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false)
|
||||
assertThat(underTestWithoutPower.power).isNull()
|
||||
@@ -114,7 +116,7 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun userSwitcher() = runBlockingTest {
|
||||
fun userSwitcher() = runTest {
|
||||
val picture: Drawable = mock()
|
||||
val userInfoController = FakeUserInfoController(FakeInfo(picture = picture))
|
||||
val settings = FakeSettings()
|
||||
@@ -135,7 +137,6 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
showPowerButton = false,
|
||||
footerActionsInteractor =
|
||||
utils.footerActionsInteractor(
|
||||
bgDispatcher = testDispatcher,
|
||||
userSwitcherRepository =
|
||||
utils.userSwitcherRepository(
|
||||
userTracker = userTracker,
|
||||
@@ -143,22 +144,12 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
userManager = userManager,
|
||||
userInfoController = userInfoController,
|
||||
userSwitcherController = userSwitcherControllerWrapper.controller,
|
||||
bgDispatcher = testDispatcher,
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
// Collect the user switcher into currentUserSwitcher.
|
||||
var currentUserSwitcher: FooterActionsButtonViewModel? = null
|
||||
val job = launch { underTest.userSwitcher.collect { currentUserSwitcher = it } }
|
||||
fun currentUserSwitcher(): FooterActionsButtonViewModel? {
|
||||
// Make sure we finish collecting the current user switcher. This is necessary because
|
||||
// combined flows launch multiple coroutines in the current scope so we need to make
|
||||
// sure we process all coroutines triggered by our flow collection before we make
|
||||
// assertions on the current buttons.
|
||||
advanceUntilIdle()
|
||||
return currentUserSwitcher
|
||||
}
|
||||
val currentUserSwitcher = collectLastValue(underTest.userSwitcher)
|
||||
|
||||
// The user switcher is disabled.
|
||||
assertThat(currentUserSwitcher()).isNull()
|
||||
@@ -203,12 +194,10 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
// in guest mode.
|
||||
userInfoController.updateInfo { this.picture = mock<UserIconDrawable>() }
|
||||
assertThat(iconTint()).isNull()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun security() = runBlockingTest {
|
||||
fun security() = runTest {
|
||||
val securityController = FakeSecurityController()
|
||||
val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
|
||||
|
||||
@@ -224,22 +213,15 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
footerActionsInteractor =
|
||||
utils.footerActionsInteractor(
|
||||
qsSecurityFooterUtils = qsSecurityFooterUtils,
|
||||
bgDispatcher = testDispatcher,
|
||||
securityRepository =
|
||||
utils.securityRepository(
|
||||
securityController = securityController,
|
||||
bgDispatcher = testDispatcher,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
// Collect the security model into currentSecurity.
|
||||
var currentSecurity: FooterActionsSecurityButtonViewModel? = null
|
||||
val job = launch { underTest.security.collect { currentSecurity = it } }
|
||||
fun currentSecurity(): FooterActionsSecurityButtonViewModel? {
|
||||
advanceUntilIdle()
|
||||
return currentSecurity
|
||||
}
|
||||
val currentSecurity = collectLastValue(underTest.security)
|
||||
|
||||
// By default, we always return a null SecurityButtonConfig.
|
||||
assertThat(currentSecurity()).isNull()
|
||||
@@ -270,12 +252,10 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
security = currentSecurity()
|
||||
assertThat(security).isNotNull()
|
||||
assertThat(security!!.onClick).isNull()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun foregroundServices() = runBlockingTest {
|
||||
fun foregroundServices() = runTest {
|
||||
val securityController = FakeSecurityController()
|
||||
val fgsManagerController =
|
||||
FakeFgsManagerController(
|
||||
@@ -300,21 +280,14 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
securityRepository =
|
||||
utils.securityRepository(
|
||||
securityController,
|
||||
bgDispatcher = testDispatcher,
|
||||
),
|
||||
foregroundServicesRepository =
|
||||
utils.foregroundServicesRepository(fgsManagerController),
|
||||
bgDispatcher = testDispatcher,
|
||||
),
|
||||
)
|
||||
|
||||
// Collect the security model into currentSecurity.
|
||||
var currentForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null
|
||||
val job = launch { underTest.foregroundServices.collect { currentForegroundServices = it } }
|
||||
fun currentForegroundServices(): FooterActionsForegroundServicesButtonViewModel? {
|
||||
advanceUntilIdle()
|
||||
return currentForegroundServices
|
||||
}
|
||||
val currentForegroundServices = collectLastValue(underTest.foregroundServices)
|
||||
|
||||
// We don't show the foreground services button if the number of running packages is not
|
||||
// > 1.
|
||||
@@ -356,12 +329,10 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
}
|
||||
securityController.updateState {}
|
||||
assertThat(currentForegroundServices()?.displayText).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun observeDeviceMonitoringDialogRequests() = runBlockingTest {
|
||||
fun observeDeviceMonitoringDialogRequests() = runTest {
|
||||
val qsSecurityFooterUtils = mock<QSSecurityFooterUtils>()
|
||||
val broadcastDispatcher = mock<BroadcastDispatcher>()
|
||||
|
||||
@@ -390,7 +361,6 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
utils.footerActionsInteractor(
|
||||
qsSecurityFooterUtils = qsSecurityFooterUtils,
|
||||
broadcastDispatcher = broadcastDispatcher,
|
||||
bgDispatcher = testDispatcher,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -415,7 +385,4 @@ class FooterActionsViewModelTest : SysuiTestCase() {
|
||||
underTest.onVisibilityChangeRequested(visible = true)
|
||||
assertThat(underTest.isVisible.value).isTrue()
|
||||
}
|
||||
|
||||
private fun runBlockingTest(block: suspend TestScope.() -> Unit) =
|
||||
runTest(testDispatcher) { block() }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.systemui.coroutines
|
||||
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
|
||||
/** Collect [flow] in a new [Job] and return a getter for the last collected value. */
|
||||
fun <T> TestScope.collectLastValue(
|
||||
flow: Flow<T>,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||
): () -> T? {
|
||||
var lastValue: T? = null
|
||||
backgroundScope.launch(context, start) { flow.collect { lastValue = it } }
|
||||
return {
|
||||
runCurrent()
|
||||
lastValue
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,8 @@ import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.android.systemui.util.settings.GlobalSettings
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestCoroutineScheduler
|
||||
|
||||
/**
|
||||
* Util class to create real implementations of the FooterActions repositories, viewModel and
|
||||
@@ -65,6 +66,7 @@ import kotlinx.coroutines.test.TestCoroutineDispatcher
|
||||
class FooterActionsTestUtils(
|
||||
private val context: Context,
|
||||
private val testableLooper: TestableLooper,
|
||||
private val scheduler: TestCoroutineScheduler,
|
||||
) {
|
||||
/** Enable or disable the user switcher in the settings. */
|
||||
fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean, userId: Int) {
|
||||
@@ -105,7 +107,7 @@ class FooterActionsTestUtils(
|
||||
foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(),
|
||||
userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(),
|
||||
broadcastDispatcher: BroadcastDispatcher = mock(),
|
||||
bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
|
||||
bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
|
||||
): FooterActionsInteractor {
|
||||
return FooterActionsInteractorImpl(
|
||||
activityStarter,
|
||||
@@ -126,7 +128,7 @@ class FooterActionsTestUtils(
|
||||
/** Create a [SecurityRepository] to be used in tests. */
|
||||
fun securityRepository(
|
||||
securityController: SecurityController = FakeSecurityController(),
|
||||
bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
|
||||
bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
|
||||
): SecurityRepository {
|
||||
return SecurityRepositoryImpl(
|
||||
securityController,
|
||||
@@ -145,7 +147,7 @@ class FooterActionsTestUtils(
|
||||
fun userSwitcherRepository(
|
||||
@Application context: Context = this.context.applicationContext,
|
||||
bgHandler: Handler = Handler(testableLooper.looper),
|
||||
bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(),
|
||||
bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler),
|
||||
userManager: UserManager = mock(),
|
||||
userTracker: UserTracker = FakeUserTracker(),
|
||||
userSwitcherController: UserSwitcherController = mock(),
|
||||
|
||||
Reference in New Issue
Block a user