1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.permission.persistence
18 
19 import android.content.ApexEnvironment
20 import android.content.Context
21 import android.os.Process
22 import android.os.UserHandle
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.platform.app.InstrumentationRegistry
25 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
26 import com.google.common.truth.Truth.assertThat
27 import java.io.File
28 import org.junit.After
29 import org.junit.Before
30 import org.junit.Test
31 import org.junit.runner.RunWith
32 import org.mockito.ArgumentMatchers.any
33 import org.mockito.ArgumentMatchers.eq
34 import org.mockito.Mock
35 import org.mockito.Mockito.`when`
36 import org.mockito.MockitoAnnotations.initMocks
37 import org.mockito.MockitoSession
38 import org.mockito.quality.Strictness
39 
40 @RunWith(AndroidJUnit4::class)
41 class RuntimePermissionsPersistenceTest {
42     private val context = InstrumentationRegistry.getInstrumentation().context
43 
44     private lateinit var mockDataDirectory: File
45 
46     private lateinit var mockitoSession: MockitoSession
47     @Mock lateinit var apexEnvironment: ApexEnvironment
48 
<lambda>null49     private val persistence = RuntimePermissionsPersistenceImpl {}
50     private val permissionState = RuntimePermissionsState.PermissionState("permission", true, 3)
51     private val state =
52         RuntimePermissionsState(
53             1,
54             "fingerprint",
55             mapOf("package" to listOf(permissionState)),
56             mapOf("sharedUser" to listOf(permissionState))
57         )
58     private val user = Process.myUserHandle()
59 
60     @Before
createMockDataDirectorynull61     fun createMockDataDirectory() {
62         mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE)
63         mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() }
64     }
65 
66     @Before
mockApexEnvironmentnull67     fun mockApexEnvironment() {
68         initMocks(this)
69         mockitoSession =
70             mockitoSession()
71                 .mockStatic(ApexEnvironment::class.java)
72                 .strictness(Strictness.LENIENT)
73                 .startMocking()
74         `when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment)
75         `when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then {
76             File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() }
77         }
78     }
79 
80     @After
finishMockingApexEnvironmentnull81     fun finishMockingApexEnvironment() {
82         mockitoSession.finishMocking()
83     }
84 
85     @Test
testWriteReadnull86     fun testWriteRead() {
87         persistence.writeForUser(state, user)
88         val persistedState = persistence.readForUser(user)
89 
90         checkPersistedState(persistedState!!)
91     }
92 
93     @Test
testWriteCorruptReadFromReserveCopynull94     fun testWriteCorruptReadFromReserveCopy() {
95         persistence.writeForUser(state, user)
96         // Corrupt the primary file.
97         RuntimePermissionsPersistenceImpl.getFile(user)
98             .writeText(
99                 "<runtime-permissions version=\"10\"><package name=\"com.foo.bar\"><permission"
100             )
101         val persistedState = persistence.readForUser(user)
102 
103         checkPersistedState(persistedState!!)
104     }
105 
106     @Test
testDeletenull107     fun testDelete() {
108         persistence.writeForUser(state, user)
109         persistence.deleteForUser(user)
110         val persistedState = persistence.readForUser(user)
111 
112         assertThat(persistedState).isNull()
113     }
114 
checkPersistedStatenull115     private fun checkPersistedState(persistedState: RuntimePermissionsState) {
116         assertThat(persistedState).isEqualTo(state)
117         assertThat(persistedState.version).isEqualTo(state.version)
118         assertThat(persistedState.fingerprint).isEqualTo(state.fingerprint)
119         assertThat(persistedState.packagePermissions).isEqualTo(state.packagePermissions)
120         val persistedPermissionState = persistedState.packagePermissions.values.first().first()
121         assertThat(persistedPermissionState.name).isEqualTo(permissionState.name)
122         assertThat(persistedPermissionState.isGranted).isEqualTo(permissionState.isGranted)
123         assertThat(persistedPermissionState.flags).isEqualTo(permissionState.flags)
124         assertThat(persistedState.sharedUserPermissions).isEqualTo(state.sharedUserPermissions)
125     }
126 
127     companion object {
128         private const val APEX_MODULE_NAME = "com.android.permission"
129     }
130 }
131