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.role.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.platform.app.InstrumentationRegistry 24 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession 25 import com.google.common.truth.Truth.assertThat 26 import java.io.File 27 import org.junit.After 28 import org.junit.Before 29 import org.junit.Test 30 import org.junit.runner.RunWith 31 import org.junit.runners.Parameterized 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(Parameterized::class) 41 class RolesPersistenceTest { 42 private val context = InstrumentationRegistry.getInstrumentation().context 43 44 private lateinit var mockDataDirectory: File 45 private lateinit var mockitoSession: MockitoSession 46 @Mock lateinit var apexEnvironment: ApexEnvironment 47 @Parameterized.Parameter(0) lateinit var stateVersion: StateVersion 48 private lateinit var state: RolesState 49 <lambda>null50 private val persistence = RolesPersistenceImpl {} 51 private val defaultRoles = mapOf(ROLE_NAME to setOf(HOLDER_1, HOLDER_2)) 52 private val stateVersionUndefined = RolesState(VERSION_UNDEFINED, PACKAGE_HASH, defaultRoles) 53 private val stateVersionFallbackMigrated = 54 RolesState(VERSION_FALLBACK_MIGRATED, PACKAGE_HASH, defaultRoles, setOf(ROLE_NAME)) 55 private val user = Process.myUserHandle() 56 57 @Before setUpnull58 fun setUp() { 59 createMockDataDirectory() 60 mockApexEnvironment() 61 state = getState() 62 } 63 createMockDataDirectorynull64 private fun createMockDataDirectory() { 65 mockDataDirectory = context.getDir("mock_data", Context.MODE_PRIVATE) 66 mockDataDirectory.listFiles()!!.forEach { assertThat(it.deleteRecursively()).isTrue() } 67 } 68 mockApexEnvironmentnull69 private fun mockApexEnvironment() { 70 initMocks(this) 71 mockitoSession = 72 mockitoSession() 73 .mockStatic(ApexEnvironment::class.java) 74 .strictness(Strictness.LENIENT) 75 .startMocking() 76 `when`(ApexEnvironment.getApexEnvironment(eq(APEX_MODULE_NAME))).thenReturn(apexEnvironment) 77 `when`(apexEnvironment.getDeviceProtectedDataDirForUser(any(UserHandle::class.java))).then { 78 File(mockDataDirectory, it.arguments[0].toString()).also { it.mkdirs() } 79 } 80 } 81 82 @After finishMockingApexEnvironmentnull83 fun finishMockingApexEnvironment() { 84 mockitoSession.finishMocking() 85 } 86 87 @Test testWriteReadnull88 fun testWriteRead() { 89 persistence.writeForUser(state, user) 90 val persistedState = persistence.readForUser(user) 91 92 assertThat(persistedState).isEqualTo(state) 93 } 94 95 @Test testWriteCorruptReadFromReserveCopynull96 fun testWriteCorruptReadFromReserveCopy() { 97 persistence.writeForUser(state, user) 98 // Corrupt the primary file. 99 RolesPersistenceImpl.getFile(user) 100 .writeText("<roles version=\"-1\"><role name=\"com.foo.bar\"><holder") 101 val persistedState = persistence.readForUser(user) 102 103 assertThat(persistedState).isEqualTo(state) 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 getStatenull115 private fun getState(): RolesState = 116 when (stateVersion) { 117 StateVersion.VERSION_UNDEFINED -> stateVersionUndefined 118 StateVersion.VERSION_FALLBACK_MIGRATED -> stateVersionFallbackMigrated 119 } 120 121 enum class StateVersion { 122 VERSION_UNDEFINED, 123 VERSION_FALLBACK_MIGRATED 124 } 125 126 companion object { 127 @Parameterized.Parameters(name = "{0}") 128 @JvmStatic datanull129 fun data(): Array<StateVersion> = StateVersion.values() 130 131 private const val VERSION_UNDEFINED = -1 132 private const val VERSION_FALLBACK_MIGRATED = 1 133 private const val APEX_MODULE_NAME = "com.android.permission" 134 private const val PACKAGE_HASH = "packagesHash" 135 private const val ROLE_NAME = "roleName" 136 private const val HOLDER_1 = "holder1" 137 private const val HOLDER_2 = "holder2" 138 } 139 } 140