1 /* 2 * Copyright (C) 2015 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.managedprovisioning.task; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 import static org.junit.Assert.fail; 23 import static org.mockito.Mockito.verify; 24 import static org.mockito.Mockito.verifyNoMoreInteractions; 25 import static org.mockito.Mockito.when; 26 27 import android.content.Context; 28 import android.content.pm.IPackageDeleteObserver; 29 import android.content.pm.PackageInfo; 30 import android.content.pm.PackageManager; 31 import android.os.RemoteException; 32 import android.support.test.InstrumentationRegistry; 33 import android.support.test.filters.SmallTest; 34 import android.test.mock.MockPackageManager; 35 36 import com.android.managedprovisioning.model.ProvisioningParams; 37 import com.android.managedprovisioning.task.nonrequiredapps.NonRequiredAppsLogic; 38 39 import java.util.Arrays; 40 import java.util.Collections; 41 import java.util.HashSet; 42 import java.util.Set; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 49 @SmallTest 50 public class DeleteNonRequiredAppsTaskTest { 51 private static final String TEST_DPC_PACKAGE_NAME = "dpc.package.name"; 52 private static final int TEST_USER_ID = 123; 53 private static final ProvisioningParams TEST_PARAMS = new ProvisioningParams.Builder() 54 .setProvisioningAction(ACTION_PROVISION_MANAGED_DEVICE) 55 .setDeviceAdminPackageName(TEST_DPC_PACKAGE_NAME) 56 .build(); 57 58 private @Mock AbstractProvisioningTask.Callback mCallback; 59 private @Mock Context mTestContext; 60 private @Mock NonRequiredAppsLogic mLogic; 61 62 private FakePackageManager mPackageManager; 63 private Set<String> mDeletedApps; 64 private DeleteNonRequiredAppsTask mTask; 65 66 @Before 67 public void setUp() throws Exception { 68 MockitoAnnotations.initMocks(this); 69 70 mPackageManager = new FakePackageManager(); 71 72 when(mTestContext.getPackageManager()).thenReturn(mPackageManager); 73 when(mTestContext.getFilesDir()).thenReturn(InstrumentationRegistry.getTargetContext() 74 .getFilesDir()); 75 76 mDeletedApps = new HashSet<>(); 77 78 mTask = new DeleteNonRequiredAppsTask(mTestContext, TEST_PARAMS, mCallback, mLogic); 79 } 80 81 @Test 82 public void testNoAppsToDelete() { 83 // GIVEN that no apps should be deleted 84 when(mLogic.getSystemAppsToRemove(TEST_USER_ID)).thenReturn(Collections.emptySet()); 85 mPackageManager.setInstalledApps(setFromArray("app.a")); 86 87 // WHEN running the task 88 mTask.run(TEST_USER_ID); 89 90 // THEN maybe take snapshot should have been called 91 verify(mLogic).maybeTakeSystemAppsSnapshot(TEST_USER_ID); 92 93 // THEN success should be called 94 verify(mCallback).onSuccess(mTask); 95 verifyNoMoreInteractions(mCallback); 96 97 // THEN no apps should have been deleted 98 assertDeletedApps(); 99 } 100 101 @Test 102 public void testAppsToDelete() { 103 // GIVEN that some apps should be deleted 104 when(mLogic.getSystemAppsToRemove(TEST_USER_ID)) 105 .thenReturn(setFromArray("app.a", "app.b")); 106 // GIVEN that only app a is currently installed 107 mPackageManager.setInstalledApps(setFromArray("app.a", "app.c")); 108 109 // WHEN running the task 110 mTask.run(TEST_USER_ID); 111 112 // THEN maybe take snapshot should have been called 113 verify(mLogic).maybeTakeSystemAppsSnapshot(TEST_USER_ID); 114 115 // THEN success should be called 116 verify(mCallback).onSuccess(mTask); 117 verifyNoMoreInteractions(mCallback); 118 119 // THEN those apps should have been deleted 120 assertDeletedApps("app.a"); 121 } 122 123 @Test 124 public void testAllAppsAlreadyDeleted() { 125 // GIVEN that some apps should be deleted 126 when(mLogic.getSystemAppsToRemove(TEST_USER_ID)) 127 .thenReturn(setFromArray("app.a", "app.b")); 128 129 // WHEN running the task 130 mTask.run(TEST_USER_ID); 131 132 // THEN maybe take snapshot should have been called 133 verify(mLogic).maybeTakeSystemAppsSnapshot(TEST_USER_ID); 134 135 // THEN success should be called 136 verify(mCallback).onSuccess(mTask); 137 verifyNoMoreInteractions(mCallback); 138 139 // THEN those apps should have been deleted 140 assertDeletedApps(); 141 } 142 143 @Test 144 public void testDeletionFailed() { 145 // GIVEN that one app should be deleted 146 when(mLogic.getSystemAppsToRemove(TEST_USER_ID)) 147 .thenReturn(setFromArray("app.a")); 148 mPackageManager.setInstalledApps(setFromArray("app.a")); 149 150 // GIVEN that deletion fails 151 mPackageManager.setDeletionSucceeds(false); 152 153 // WHEN running the task 154 mTask.run(TEST_USER_ID); 155 156 // THEN maybe take snapshot should have been called 157 verify(mLogic).maybeTakeSystemAppsSnapshot(TEST_USER_ID); 158 159 // THEN error should be returned 160 verify(mCallback).onError(mTask, 0); 161 verifyNoMoreInteractions(mCallback); 162 } 163 164 private <T> Set<T> setFromArray(T... array) { 165 if (array == null) { 166 return null; 167 } 168 return new HashSet<>(Arrays.asList(array)); 169 } 170 171 private void assertDeletedApps(String... appArray) { 172 assertEquals(setFromArray(appArray), mDeletedApps); 173 } 174 175 176 class FakePackageManager extends MockPackageManager { 177 private boolean mDeletionSucceeds = true; 178 private Set<String> mInstalledApps = new HashSet<>(); 179 180 void setDeletionSucceeds(boolean deletionSucceeds) { 181 mDeletionSucceeds = deletionSucceeds; 182 } 183 184 void setInstalledApps(Set<String> set) { 185 mInstalledApps = set; 186 } 187 188 @Override 189 public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, 190 int flags, int userId) { 191 if (mDeletionSucceeds) { 192 mDeletedApps.add(packageName); 193 } 194 assertTrue((flags & PackageManager.DELETE_SYSTEM_APP) != 0); 195 assertEquals(TEST_USER_ID, userId); 196 197 int resultCode; 198 if (mDeletionSucceeds) { 199 resultCode = PackageManager.DELETE_SUCCEEDED; 200 } else { 201 resultCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR; 202 } 203 assertTrue(mInstalledApps.remove(packageName)); 204 205 try { 206 observer.packageDeleted(packageName, resultCode); 207 } catch (RemoteException e) { 208 fail(e.toString()); 209 } 210 } 211 212 @Override 213 public PackageInfo getPackageInfoAsUser(String pkg, int flag, int userId) 214 throws NameNotFoundException { 215 if (mInstalledApps.contains(pkg) && userId == TEST_USER_ID) { 216 return new PackageInfo(); 217 } 218 throw new NameNotFoundException(); 219 } 220 } 221 } 222