Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 723f9d25 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Automerger Merge Worker
Browse files

Merge changes Ia3b1ae8f,Ie87220a7 into tm-qpr-dev am: 52c7bc24 am: b28ae70b

parents d9cae77b b28ae70b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+16 −49
Original line number Diff line number Diff line
@@ -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() }
}
+40 −0
Original line number Diff line number Diff line
/*
 * 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
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -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(),