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

Commit b62b890b authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "Migrate AppPermissionSummaryTest to AndroidJUnit4"

parents dbd95eb4 681b519b
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -37,19 +37,19 @@ class AppPermissionSummaryLiveData(
    private val app: ApplicationInfo,
) : LiveData<AppPermissionSummaryState>() {
    private val userContext = context.asUser(app.userHandle)
    private val packageManager = userContext.packageManager
    private val userPackageManager = userContext.packageManager

    private val onPermissionsChangedListener = OnPermissionsChangedListener { uid ->
        if (uid == app.uid) update()
    }

    override fun onActive() {
        packageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
        userPackageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
        update()
    }

    override fun onInactive() {
        packageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
        userPackageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
    }

    private fun update() {
@@ -69,13 +69,11 @@ class AppPermissionSummaryLiveData(
                return
            }
            val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
            val summary = when {
                labels.isEmpty() -> {
            val summary = if (labels.isNotEmpty()) {
                ListFormatter.getInstance().format(labels)
            } else {
                context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
            }

                else -> ListFormatter.getInstance().format(labels)
            }
            postValue(AppPermissionSummaryState(summary = summary, enabled = true))
        }
    }
+59 −77
Original line number Diff line number Diff line
@@ -19,16 +19,17 @@ package com.android.settings.spa.app.appinfo
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.settings.R
import com.android.settings.testutils.mockAsUser
import com.android.settingslib.applications.PermissionsSummaryHelper
import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
import com.android.settingslib.spa.testutils.getOrAwaitValue
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -39,22 +40,17 @@ import org.mockito.Mockito.doReturn
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoSession
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.annotation.Implementation
import org.robolectric.annotation.Implements
import org.mockito.quality.Strictness
import org.mockito.Mockito.`when` as whenever

@RunWith(RobolectricTestRunner::class)
@Config(shadows = [ShadowPermissionsSummaryHelper::class])
@RunWith(AndroidJUnit4::class)
class AppPermissionSummaryTest {
    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    @JvmField
    @Rule
    val mockito: MockitoRule = MockitoJUnit.rule()
    private lateinit var mockSession: MockitoSession

    @Spy
    private var context: Context = ApplicationProvider.getApplicationContext()
@@ -66,27 +62,53 @@ class AppPermissionSummaryTest {

    @Before
    fun setUp() {
        doReturn(context).`when`(context).createContextAsUser(any(), eq(0))
        mockSession = mockitoSession()
            .initMocks(this)
            .mockStatic(PermissionsSummaryHelper::class.java)
            .strictness(Strictness.LENIENT)
            .startMocking()
        context.mockAsUser()
        whenever(context.packageManager).thenReturn(packageManager)

        val app = ApplicationInfo().apply {
            packageName = PACKAGE_NAME
        summaryLiveData = AppPermissionSummaryLiveData(context, APP)
    }

    private fun mockGetPermissionSummary(
        requestedPermissionCount: Int = 0,
        additionalGrantedPermissionCount: Int = 0,
        grantedGroupLabels: List<CharSequence> = emptyList(),
    ) {
        whenever(PermissionsSummaryHelper.getPermissionSummary(any(), eq(PACKAGE_NAME), any()))
            .thenAnswer {
                val callback = it.arguments[2] as PermissionsResultCallback
                callback.onPermissionSummaryResult(
                    requestedPermissionCount,
                    additionalGrantedPermissionCount,
                    grantedGroupLabels,
                )
            }
        summaryLiveData = AppPermissionSummaryLiveData(context, app)
    }

    @After
    fun tearDown() {
        mockSession.finishMocking()
    }

    @Test
    fun permissionsChangeListener() {
        mockGetPermissionSummary()

        summaryLiveData.getOrAwaitValue {
            verify(packageManager).addOnPermissionsChangeListener(any())
            verify(packageManager, never()).removeOnPermissionsChangeListener(any())
        }

        verify(packageManager).removeOnPermissionsChangeListener(any())
    }

    @Test
    fun summary_noPermissionsRequested() {
        ShadowPermissionsSummaryHelper.requestedPermissionCount = 0
        mockGetPermissionSummary(requestedPermissionCount = 0)

        val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!

@@ -98,8 +120,7 @@ class AppPermissionSummaryTest {

    @Test
    fun summary_noPermissionsGranted() {
        ShadowPermissionsSummaryHelper.requestedPermissionCount = 1
        ShadowPermissionsSummaryHelper.grantedGroupLabels = emptyList()
        mockGetPermissionSummary(requestedPermissionCount = 1, grantedGroupLabels = emptyList())

        val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!

@@ -111,8 +132,10 @@ class AppPermissionSummaryTest {

    @Test
    fun onPermissionSummaryResult_hasRuntimePermission_shouldSetPermissionAsSummary() {
        ShadowPermissionsSummaryHelper.requestedPermissionCount = 1
        ShadowPermissionsSummaryHelper.grantedGroupLabels = listOf(PERMISSION)
        mockGetPermissionSummary(
            requestedPermissionCount = 1,
            grantedGroupLabels = listOf(PERMISSION),
        )

        val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!

@@ -122,9 +145,11 @@ class AppPermissionSummaryTest {

    @Test
    fun onPermissionSummaryResult_hasAdditionalPermission_shouldSetAdditionalSummary() {
        ShadowPermissionsSummaryHelper.requestedPermissionCount = 5
        ShadowPermissionsSummaryHelper.additionalGrantedPermissionCount = 2
        ShadowPermissionsSummaryHelper.grantedGroupLabels = listOf(PERMISSION)
        mockGetPermissionSummary(
            requestedPermissionCount = 5,
            additionalGrantedPermissionCount = 2,
            grantedGroupLabels = listOf(PERMISSION),
        )

        val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!

@@ -132,54 +157,11 @@ class AppPermissionSummaryTest {
        assertThat(enabled).isTrue()
    }

    companion object {
        private const val PACKAGE_NAME = "packageName"
        private const val PERMISSION = "Storage"
    }
}

@Implements(PermissionsSummaryHelper::class)
private object ShadowPermissionsSummaryHelper {
    var requestedPermissionCount = 0
    var additionalGrantedPermissionCount = 0
    var grantedGroupLabels: List<CharSequence> = emptyList()

    @Implementation
    @JvmStatic
    @Suppress("UNUSED_PARAMETER")
    fun getPermissionSummary(context: Context, pkg: String, callback: PermissionsResultCallback) {
        callback.onPermissionSummaryResult(
            requestedPermissionCount,
            additionalGrantedPermissionCount,
            grantedGroupLabels,
        )
    }
}

private fun <T> LiveData<T>.getOrAwaitValue(
    time: Long = 2,
    timeUnit: TimeUnit = TimeUnit.SECONDS,
    afterObserve: () -> Unit = {},
): T? {
    var data: T? = null
    val latch = CountDownLatch(1)
    val observer = Observer<T> { o ->
        data = o
        latch.countDown()
    }
    this.observeForever(observer)

    afterObserve()

    try {
        // Don't wait indefinitely if the LiveData is not set.
        if (!latch.await(time, timeUnit)) {
            throw TimeoutException("LiveData value was never set.")
    private companion object {
        const val PACKAGE_NAME = "packageName"
        const val PERMISSION = "Storage"
        val APP = ApplicationInfo().apply {
            packageName = PACKAGE_NAME
        }

    } finally {
        this.removeObserver(observer)
    }

    return data
}