Make DPM/DPMS unit-testable

- Now all services that DPMS uses are injectable.
- Introduce some wrappers to make static methods and final class mockable.
(e.g. for Binder.getCallingUid())

- In unit tests we replace those with Mockito mocks, except we use a partial
mock for PackageManager, because we use way too many methods of this and
most of them are okay to use directly.

- To install a partial mock to PackageManager, I needed to make
ApplicationPackageManager @hide public non-final.

- For a starter, added tests for DPM.setAmin().

Bug 24061108

Change-Id: I2afd51d8bc0038992d5f9be38c686260be775b75
This commit is contained in:
Makoto Onuki
2015-09-17 10:28:24 -07:00
parent 99c2760ed0
commit cc4bbeb76a
15 changed files with 1240 additions and 340 deletions

View File

@@ -93,8 +93,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
/*package*/
final class ApplicationPackageManager extends PackageManager {
/** @hide */
public class ApplicationPackageManager extends PackageManager {
private static final String TAG = "ApplicationPackageManager";
private final static boolean DEBUG_ICONS = false;

View File

@@ -240,7 +240,7 @@ final class SystemServiceRegistry {
new CachedServiceFetcher<DevicePolicyManager>() {
@Override
public DevicePolicyManager createService(ContextImpl ctx) {
return DevicePolicyManager.create(ctx, ctx.mMainThread.getHandler());
return DevicePolicyManager.create(ctx);
}});
registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class,

View File

@@ -32,7 +32,6 @@ import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
@@ -45,6 +44,7 @@ import android.security.Credentials;
import android.service.restrictions.RestrictionsReceiver;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.org.conscrypt.TrustedCertificateStore;
import org.xmlpull.v1.XmlPullParserException;
@@ -87,18 +87,30 @@ public class DevicePolicyManager {
private final Context mContext;
private final IDevicePolicyManager mService;
private DevicePolicyManager(Context context, Handler handler) {
mContext = context;
mService = IDevicePolicyManager.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
private DevicePolicyManager(Context context) {
this(context, IDevicePolicyManager.Stub.asInterface(
ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)));
}
/** @hide */
public static DevicePolicyManager create(Context context, Handler handler) {
DevicePolicyManager me = new DevicePolicyManager(context, handler);
@VisibleForTesting
protected DevicePolicyManager(Context context, IDevicePolicyManager service) {
mContext = context;
mService = service;
}
/** @hide */
public static DevicePolicyManager create(Context context) {
DevicePolicyManager me = new DevicePolicyManager(context);
return me.mService != null ? me : null;
}
/** @hide test will override it. */
@VisibleForTesting
protected int myUserId() {
return UserHandle.myUserId();
}
/**
* Activity action: Starts the provisioning flow which sets up a managed profile.
*
@@ -823,7 +835,7 @@ public class DevicePolicyManager {
* active (enabled) in the system.
*/
public boolean isAdminActive(@NonNull ComponentName admin) {
return isAdminActiveAsUser(admin, UserHandle.myUserId());
return isAdminActiveAsUser(admin, myUserId());
}
/**
@@ -863,7 +875,7 @@ public class DevicePolicyManager {
* returned.
*/
public List<ComponentName> getActiveAdmins() {
return getActiveAdminsAsUser(UserHandle.myUserId());
return getActiveAdminsAsUser(myUserId());
}
/**
@@ -889,7 +901,7 @@ public class DevicePolicyManager {
public boolean packageHasActiveAdmins(String packageName) {
if (mService != null) {
try {
return mService.packageHasActiveAdmins(packageName, UserHandle.myUserId());
return mService.packageHasActiveAdmins(packageName, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -906,7 +918,7 @@ public class DevicePolicyManager {
public void removeActiveAdmin(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.removeActiveAdmin(admin, UserHandle.myUserId());
mService.removeActiveAdmin(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -925,7 +937,7 @@ public class DevicePolicyManager {
public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
if (mService != null) {
try {
return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1040,7 +1052,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getPasswordQuality(@Nullable ComponentName admin) {
return getPasswordQuality(admin, UserHandle.myUserId());
return getPasswordQuality(admin, myUserId());
}
/** @hide per-user version */
@@ -1093,7 +1105,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getPasswordMinimumLength(@Nullable ComponentName admin) {
return getPasswordMinimumLength(admin, UserHandle.myUserId());
return getPasswordMinimumLength(admin, myUserId());
}
/** @hide per-user version */
@@ -1154,7 +1166,7 @@ public class DevicePolicyManager {
* password.
*/
public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
return getPasswordMinimumUpperCase(admin, myUserId());
}
/** @hide per-user version */
@@ -1215,7 +1227,7 @@ public class DevicePolicyManager {
* password.
*/
public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
return getPasswordMinimumLowerCase(admin, myUserId());
}
/** @hide per-user version */
@@ -1273,7 +1285,7 @@ public class DevicePolicyManager {
* @return The minimum number of letters required in the password.
*/
public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
return getPasswordMinimumLetters(admin, UserHandle.myUserId());
return getPasswordMinimumLetters(admin, myUserId());
}
/** @hide per-user version */
@@ -1332,7 +1344,7 @@ public class DevicePolicyManager {
* @return The minimum number of numerical digits required in the password.
*/
public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
return getPasswordMinimumNumeric(admin, myUserId());
}
/** @hide per-user version */
@@ -1390,7 +1402,7 @@ public class DevicePolicyManager {
* @return The minimum number of symbols required in the password.
*/
public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
return getPasswordMinimumSymbols(admin, myUserId());
}
/** @hide per-user version */
@@ -1449,7 +1461,7 @@ public class DevicePolicyManager {
* @return The minimum number of letters required in the password.
*/
public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
return getPasswordMinimumNonLetter(admin, myUserId());
}
/** @hide per-user version */
@@ -1540,7 +1552,7 @@ public class DevicePolicyManager {
public long getPasswordExpirationTimeout(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
return mService.getPasswordExpirationTimeout(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1561,7 +1573,7 @@ public class DevicePolicyManager {
public long getPasswordExpiration(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpiration(admin, UserHandle.myUserId());
return mService.getPasswordExpiration(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1577,7 +1589,7 @@ public class DevicePolicyManager {
* @return The length of the password history
*/
public int getPasswordHistoryLength(@Nullable ComponentName admin) {
return getPasswordHistoryLength(admin, UserHandle.myUserId());
return getPasswordHistoryLength(admin, myUserId());
}
/** @hide per-user version */
@@ -1617,7 +1629,7 @@ public class DevicePolicyManager {
public boolean isActivePasswordSufficient() {
if (mService != null) {
try {
return mService.isActivePasswordSufficient(UserHandle.myUserId());
return mService.isActivePasswordSufficient(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1636,7 +1648,7 @@ public class DevicePolicyManager {
public int getCurrentFailedPasswordAttempts() {
if (mService != null) {
try {
return mService.getCurrentFailedPasswordAttempts(UserHandle.myUserId());
return mService.getCurrentFailedPasswordAttempts(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1698,7 +1710,7 @@ public class DevicePolicyManager {
* all admins.
*/
public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) {
return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
return getMaximumFailedPasswordsForWipe(admin, myUserId());
}
/** @hide per-user version */
@@ -1818,7 +1830,7 @@ public class DevicePolicyManager {
* all admins if admin is null. Returns 0 if there are no restrictions.
*/
public long getMaximumTimeToLock(@Nullable ComponentName admin) {
return getMaximumTimeToLock(admin, UserHandle.myUserId());
return getMaximumTimeToLock(admin, myUserId());
}
/** @hide per-user version */
@@ -1881,7 +1893,7 @@ public class DevicePolicyManager {
public void wipeData(int flags) {
if (mService != null) {
try {
mService.wipeData(flags, UserHandle.myUserId());
mService.wipeData(flags, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1995,7 +2007,7 @@ public class DevicePolicyManager {
public ComponentName getGlobalProxyAdmin() {
if (mService != null) {
try {
return mService.getGlobalProxyAdmin(UserHandle.myUserId());
return mService.getGlobalProxyAdmin(myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2145,7 +2157,7 @@ public class DevicePolicyManager {
public boolean getStorageEncryption(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getStorageEncryption(admin, UserHandle.myUserId());
return mService.getStorageEncryption(admin, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2173,7 +2185,7 @@ public class DevicePolicyManager {
* or {@link #ENCRYPTION_STATUS_ACTIVE}.
*/
public int getStorageEncryptionStatus() {
return getStorageEncryptionStatus(UserHandle.myUserId());
return getStorageEncryptionStatus(myUserId());
}
/** @hide per-user version */
@@ -2410,7 +2422,7 @@ public class DevicePolicyManager {
* have disabled the camera
*/
public boolean getCameraDisabled(@Nullable ComponentName admin) {
return getCameraDisabled(admin, UserHandle.myUserId());
return getCameraDisabled(admin, myUserId());
}
/** @hide per-user version */
@@ -2457,7 +2469,7 @@ public class DevicePolicyManager {
* have disabled screen capture.
*/
public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
return getScreenCaptureDisabled(admin, UserHandle.myUserId());
return getScreenCaptureDisabled(admin, myUserId());
}
/** @hide per-user version */
@@ -2557,7 +2569,7 @@ public class DevicePolicyManager {
* for a list.
*/
public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) {
return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
return getKeyguardDisabledFeatures(admin, myUserId());
}
/** @hide per-user version */
@@ -2590,7 +2602,7 @@ public class DevicePolicyManager {
* @hide
*/
public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
setActiveAdmin(policyReceiver, refreshing, myUserId());
}
/**
@@ -2627,7 +2639,7 @@ public class DevicePolicyManager {
public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
if (mService != null) {
try {
mService.getRemoveWarning(admin, result, UserHandle.myUserId());
mService.getRemoveWarning(admin, result, myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2956,7 +2968,7 @@ public class DevicePolicyManager {
throws IllegalArgumentException {
if (mService != null) {
try {
final int myUserId = UserHandle.myUserId();
final int myUserId = myUserId();
mService.setActiveAdmin(admin, false, myUserId);
return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
@@ -3301,7 +3313,7 @@ public class DevicePolicyManager {
*/
public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
@NonNull ComponentName agent) {
return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
return getTrustAgentConfiguration(admin, agent, myUserId());
}
/** @hide per-user version */
@@ -3927,7 +3939,7 @@ public class DevicePolicyManager {
* @see #setAccountManagementDisabled
*/
public String[] getAccountTypesWithManagementDisabled() {
return getAccountTypesWithManagementDisabledAsUser(UserHandle.myUserId());
return getAccountTypesWithManagementDisabledAsUser(myUserId());
}
/**

View File

@@ -16,6 +16,8 @@
package com.android.server;
import com.android.internal.annotations.VisibleForTesting;
import android.util.ArrayMap;
/**
@@ -57,4 +59,14 @@ public final class LocalServices {
sLocalServiceObjects.put(type, service);
}
}
/**
* Remove a service instance, must be only used in tests.
*/
@VisibleForTesting
public static <T> void removeServiceForTest(Class<T> type) {
synchronized (sLocalServiceObjects) {
sLocalServiceObjects.remove(type);
}
}
}

View File

@@ -67,6 +67,15 @@
</intent-filter>
</receiver>
<receiver android:name="com.android.server.devicepolicy.DummyDeviceAdmin"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data android:name="android.app.device_admin"
android:resource="@xml/device_admin_sample" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
<instrumentation

View File

@@ -0,0 +1,192 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import com.android.internal.widget.LockPatternUtils;
import android.app.IActivityManager;
import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Looper;
import android.os.PowerManager.WakeLock;
import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.IWindowManager;
import java.io.File;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
/**
* Overrides {@link #DevicePolicyManagerService} for dependency injection.
*/
public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerService {
/**
* Overrides {@link #Owners} for dependency injection.
*/
public static class OwnersTestable extends Owners {
public static final String LEGACY_FILE = "legacy.xml";
public static final String DEVICE_OWNER_FILE = "device_owner2.xml";
public static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
final private File mLegacyFile;
final private File mDeviceOwnerFile;
final private File mProfileOwnerBase;
public OwnersTestable(Context context, File dataDir) {
super(context);
mLegacyFile = new File(dataDir, LEGACY_FILE);
mDeviceOwnerFile = new File(dataDir, DEVICE_OWNER_FILE);
mProfileOwnerBase = new File(dataDir, PROFILE_OWNER_FILE_BASE);
}
@Override
File getLegacyConfigFileWithTestOverride() {
return mLegacyFile;
}
@Override
File getDeviceOwnerFileWithTestOverride() {
return mDeviceOwnerFile;
}
@Override
File getProfileOwnerFileWithTestOverride(int userId) {
return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
}
}
public final File dataDir;
public final File systemUserDataDir;
public final File secondUserDataDir;
public DevicePolicyManagerServiceTestable(DpmMockContext context, File dataDir) {
super(context);
this.dataDir = dataDir;
systemUserDataDir = new File(dataDir, "user0");
DpmTestUtils.clearDir(dataDir);
secondUserDataDir = new File(dataDir, "user" + DpmMockContext.CALLER_USER_HANDLE);
DpmTestUtils.clearDir(secondUserDataDir);
when(getContext().environment.getUserSystemDirectory(
eq(DpmMockContext.CALLER_USER_HANDLE))).thenReturn(secondUserDataDir);
}
@Override
DpmMockContext getContext() {
return (DpmMockContext) super.getContext();
}
@Override
protected Owners newOwners() {
return new OwnersTestable(getContext(), dataDir);
}
@Override
protected UserManager getUserManager() {
return getContext().userManager;
}
@Override
protected PackageManager getPackageManager() {
return getContext().packageManager;
}
@Override
protected PowerManagerInternal getPowerManagerInternal() {
return getContext().powerManagerInternal;
}
@Override
protected NotificationManager getNotificationManager() {
return getContext().notificationManager;
}
@Override
protected IWindowManager newIWindowManager() {
return getContext().iwindowManager;
}
@Override
protected IActivityManager getIActivityManager() {
return getContext().iactivityManager;
}
@Override
protected LockPatternUtils newLockPatternUtils(Context context) {
return getContext().lockPatternUtils;
}
@Override
protected Looper getMyLooper() {
return Looper.getMainLooper();
}
@Override
String getDevicePolicyFilePathForSystemUser() {
return systemUserDataDir.getAbsolutePath();
}
@Override
long binderClearCallingIdentity() {
return getContext().binder.clearCallingIdentity();
}
@Override
void binderRestoreCallingIdentity(long token) {
getContext().binder.restoreCallingIdentity(token);
}
@Override
int binderGetCallingUid() {
return getContext().binder.getCallingUid();
}
@Override
int binderGetCallingPid() {
return getContext().binder.getCallingPid();
}
@Override
UserHandle binderGetCallingUserHandle() {
return getContext().binder.getCallingUserHandle();
}
@Override
boolean binderIsCallingUidMyUid() {
return getContext().binder.isCallerUidMyUid();
}
@Override
File environmentGetUserSystemDirectory(int userId) {
return getContext().environment.getUserSystemDirectory(userId);
}
@Override
WakeLock powerManagerNewWakeLock(int levelAndFlags, String tag) {
return getContext().powerManager.newWakeLock(levelAndFlags, tag);
}
@Override
void powerManagerGoToSleep(long time, int reason, int flags) {
getContext().powerManager.goToSleep(time, reason, flags);
}
}

View File

@@ -0,0 +1,159 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import com.android.server.LocalServices;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import org.mockito.ArgumentCaptor;
import java.util.List;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Tests for {@link DevicePolicyManager} and {@link DevicePolicyManagerService}.
*
m FrameworksServicesTests &&
adb install \
-r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
-w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*/
public class DevicePolicyManagerTest extends DpmTestBase {
private DpmMockContext mContext;
public DevicePolicyManager dpm;
public DevicePolicyManagerServiceTestable dpms;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getContext();
when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
.thenReturn(true);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
dpms = new DevicePolicyManagerServiceTestable(mContext, dataDir);
dpm = new DevicePolicyManagerTestable(mContext, dpms);
}
public void testHasNoFeature() {
when(mContext.packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
.thenReturn(false);
LocalServices.removeServiceForTest(DevicePolicyManagerInternal.class);
new DevicePolicyManagerServiceTestable(mContext, dataDir);
// If the device has no DPMS feature, it shouldn't register the local service.
assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
}
/**
* Caller doesn't have proper permissions.
*/
public void testSetActiveAdmin_SecurityException() {
final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
// 1. Failure cases.
// Caller doesn't have MANAGE_DEVICE_ADMINS.
try {
dpm.setActiveAdmin(admin, false);
fail("Didn't throw SecurityException");
} catch (SecurityException expected) {
}
// Caller has MANAGE_DEVICE_ADMINS, but for different user.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
try {
dpm.setActiveAdmin(admin, false, DpmMockContext.CALLER_USER_HANDLE + 1);
fail("Didn't throw SecurityException");
} catch (SecurityException expected) {
}
}
public void testSetActiveAdmin() {
final ComponentName admin = new ComponentName(mRealTestContext, DummyDeviceAdmin.class);
// 1. Prepare mock package manager (and other mocks)
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
// Create ResolveInfo for the admin.
final Intent resolveIntent = new Intent();
resolveIntent.setComponent(admin);
final List<ResolveInfo> realResolveInfo =
mRealTestContext.getPackageManager().queryBroadcastReceivers(
resolveIntent,
PackageManager.GET_META_DATA
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
assertNotNull(realResolveInfo);
assertEquals(1, realResolveInfo.size());
// We need to rewrite the UID in the activity info.
realResolveInfo.get(0).activityInfo.applicationInfo.uid = DpmMockContext.CALLER_UID;
doReturn(realResolveInfo).when(mContext.packageManager).queryBroadcastReceivers(
any(Intent.class), // TODO check the intent too.
eq(PackageManager.GET_META_DATA
| PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS),
eq(DpmMockContext.CALLER_USER_HANDLE)
);
// 2. Everything is ready; call the method.
dpm.setActiveAdmin(admin, false);
// 3. Verify internal calls.
// Check if the boradcast is sent.
final ArgumentCaptor<Intent> intentCap = ArgumentCaptor.forClass(Intent.class);
final ArgumentCaptor<UserHandle> uhCap = ArgumentCaptor.forClass(UserHandle.class);
verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
intentCap.capture(),
MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
// First call from saveSettingsLocked().
assertEquals(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED,
intentCap.getAllValues().get(0).getAction());
// Second call from setActiveAdmin/sendAdminCommandLocked()
assertEquals(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
intentCap.getAllValues().get(1).getAction());
// TODO Verify other calls too.
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import android.app.admin.DevicePolicyManager;
/**
* Overrides {@link #DevicePolicyManager} for dependency injection.
*/
public class DevicePolicyManagerTestable extends DevicePolicyManager {
public final DevicePolicyManagerServiceTestable dpms;
public DevicePolicyManagerTestable(DpmMockContext context,
DevicePolicyManagerServiceTestable dpms) {
super(context, dpms);
this.dpms = dpms;
}
@Override
public int myUserId() {
return DpmMockContext.CALLER_USER_HANDLE;
}
}

View File

@@ -16,31 +16,328 @@
package com.android.server.devicepolicy;
import com.android.internal.widget.LockPatternUtils;
import android.app.IActivityManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager.WakeLock;
import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.mock.MockContext;
import android.view.IWindowManager;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
public class DpmMockContext extends ContextWrapper {
private final UserManager mMockUserManager;
/**
* Context used throughout DPMS tests.
*/
public class DpmMockContext extends MockContext {
/**
* User-id of a non-system user we use throughout unit tests.
*/
public static final int CALLER_USER_HANDLE = 20;
/**
* UID of the caller.
*/
public static final int CALLER_UID = UserHandle.PER_USER_RANGE * CALLER_USER_HANDLE + 123;
public DpmMockContext(Context context) {
super(context);
mMockUserManager = mock(UserManager.class);
/**
* PID of the caller.
*/
public static final int CALLER_PID = 22222;
/**
* UID of the system server.
*/
public static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
/**
* PID of the system server.
*/
public static final int SYSTEM_PID = 11111;
public static class MockBinder {
int mCallingUid = CALLER_UID;
int mCallingPid = CALLER_PID;
public long clearCallingIdentity() {
final long token = (((long) mCallingUid) << 32) | (mCallingPid);
mCallingUid = SYSTEM_UID;
mCallingPid = SYSTEM_PID;
return token;
}
public void restoreCallingIdentity(long token) {
mCallingUid = (int) (token >> 32);
mCallingPid = (int) token;
}
public int getCallingUid() {
return mCallingUid;
}
public int getCallingPid() {
return mCallingPid;
}
public UserHandle getCallingUserHandle() {
return new UserHandle(UserHandle.getUserId(getCallingUid()));
}
public boolean isCallerUidMyUid() {
return mCallingUid == SYSTEM_UID;
}
}
public UserManager getMockUserManager() {
return mMockUserManager;
public static class EnvironmentForMock {
public File getUserSystemDirectory(int userId) {
return null;
}
}
public static class PowerManagerForMock {
public WakeLock newWakeLock(int levelAndFlags, String tag) {
return null;
}
public void goToSleep(long time, int reason, int flags) {
}
}
public final Context realTestContext;
/**
* Use this instance to verify unimplemented methods such as {@link #sendBroadcast}.
* (Spying on {@code this} instance will confuse mockito somehow and I got weired "wrong number
* of arguments" exceptions.)
*/
public final Context spiedContext;
public final MockBinder binder;
public final EnvironmentForMock environment;
public final UserManager userManager;
public final PowerManagerForMock powerManager;
public final PowerManagerInternal powerManagerInternal;
public final NotificationManager notificationManager;
public final IWindowManager iwindowManager;
public final IActivityManager iactivityManager;
public final LockPatternUtils lockPatternUtils;
/** Note this is a partial mock, not a real mock. */
public final PackageManager packageManager;
public final List<String> callerPermissions = new ArrayList<>();
public DpmMockContext(Context context) {
realTestContext = context;
binder = new MockBinder();
environment = mock(EnvironmentForMock.class);
userManager = mock(UserManager.class);
powerManager = mock(PowerManagerForMock.class);
powerManagerInternal = mock(PowerManagerInternal.class);
notificationManager = mock(NotificationManager.class);
iwindowManager = mock(IWindowManager.class);
iactivityManager = mock(IActivityManager.class);
lockPatternUtils = mock(LockPatternUtils.class);
// Package manager is huge, so we use a partial mock instead.
packageManager = spy(context.getPackageManager());
spiedContext = mock(Context.class);
}
@Override
public Object getSystemService(String name) {
switch (name) {
case Context.USER_SERVICE:
return mMockUserManager;
return userManager;
case Context.POWER_SERVICE:
return powerManager;
}
return super.getSystemService(name);
throw new UnsupportedOperationException();
}
@Override
public PackageManager getPackageManager() {
return packageManager;
}
@Override
public void enforceCallingOrSelfPermission(String permission, String message) {
if (binder.getCallingUid() == SYSTEM_UID) {
return; // Assume system has all permissions.
}
if (!callerPermissions.contains(permission)) {
throw new SecurityException("Caller doesn't have " + permission + " : " + message);
}
}
@Override
public void sendBroadcast(Intent intent) {
spiedContext.sendBroadcast(intent);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
spiedContext.sendBroadcast(intent, receiverPermission);
}
@Override
public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
spiedContext.sendBroadcast(intent, receiverPermission, options);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
spiedContext.sendBroadcast(intent, receiverPermission, appOp);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, options, resultReceiver,
scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver,
scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
spiedContext.sendBroadcastAsUser(intent, user);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
int appOp) {
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
resultReceiver, scheduler, initialCode, initialData, initialExtras);
}
@Override
public void sendStickyBroadcast(Intent intent) {
spiedContext.sendStickyBroadcast(intent);
}
@Override
public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}
@Override
public void removeStickyBroadcast(Intent intent) {
spiedContext.removeStickyBroadcast(intent);
}
@Override
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
spiedContext.sendStickyBroadcastAsUser(intent, user);
}
@Override
public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}
@Override
public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
spiedContext.removeStickyBroadcastAsUser(intent, user);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return spiedContext.registerReceiver(receiver, filter);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
scheduler);
}
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
spiedContext.unregisterReceiver(receiver);
}
}

View File

@@ -19,14 +19,25 @@ package com.android.server.devicepolicy;
import android.content.Context;
import android.test.AndroidTestCase;
import java.io.File;
public class DpmTestBase extends AndroidTestCase {
private DpmMockContext mMockContext;
public static final String TAG = "DpmTest";
protected Context mRealTestContext;
protected DpmMockContext mMockContext;
public File dataDir;
@Override
protected void setUp() throws Exception {
super.setUp();
mRealTestContext = super.getContext();
mMockContext = new DpmMockContext(super.getContext());
dataDir = new File(mRealTestContext.getCacheDir(), "test-data");
DpmTestUtils.clearDir(dataDir);
}
@Override

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import android.os.FileUtils;
import android.util.Log;
import android.util.Printer;
import org.junit.Assert;
import java.io.File;
public class DpmTestUtils {
private DpmTestUtils() {
}
public static void clearDir(File dir) {
if (dir.exists()) {
Assert.assertTrue("failed to delete dir", FileUtils.deleteContents(dir));
}
dir.mkdirs();
}
public static Printer LOG_PRINTER = new Printer() {
@Override
public void println(String x) {
Log.i(DpmTestBase.TAG, x);
}
};
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import android.app.admin.DeviceAdminReceiver;
public class DummyDeviceAdmin extends DeviceAdminReceiver {
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 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.server.devicepolicy;
import com.google.common.base.Objects;
import android.os.UserHandle;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.Mockito;
public class MockUtils {
private MockUtils() {
}
public static UserHandle checkUserHandle(final int userId) {
final Matcher<UserHandle> m = new BaseMatcher<UserHandle>() {
@Override
public boolean matches(Object item) {
if (item == null) return false;
return Objects.equal(((UserHandle) item).getIdentifier(), userId);
}
@Override
public void describeTo(Description description) {
description.appendText("UserHandle: user-id= \"" + userId + "\"");
}
};
return Mockito.argThat(m);
}
}

View File

@@ -16,12 +16,11 @@
package com.android.server.devicepolicy;
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.UserInfo;
import android.os.FileUtils;
import android.os.UserHandle;
import android.test.AndroidTestCase;
import android.util.Log;
import java.io.BufferedReader;
@@ -31,8 +30,6 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import junit.framework.Assert;
import static org.mockito.Mockito.when;
/**
@@ -47,58 +44,11 @@ import static org.mockito.Mockito.when;
(mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*/
public class OwnersTest extends DpmTestBase {
private static final String TAG = "DeviceOwnerTest";
private static final String LEGACY_FILE = "legacy.xml";
private static final String DEVICE_OWNER_FILE = "device_owner2.xml";
private static final String PROFILE_OWNER_FILE_BASE = "profile_owner.xml";
private File mDataDir;
private class OwnersSub extends Owners {
final File mLegacyFile;
final File mDeviceOwnerFile;
final File mProfileOwnerBase;
public OwnersSub() {
super(getContext());
mLegacyFile = new File(mDataDir, LEGACY_FILE);
mDeviceOwnerFile = new File(mDataDir, DEVICE_OWNER_FILE);
mProfileOwnerBase = new File(mDataDir, PROFILE_OWNER_FILE_BASE);
}
@Override
File getLegacyConfigFileWithTestOverride() {
return mLegacyFile;
}
@Override
File getDeviceOwnerFileWithTestOverride() {
return mDeviceOwnerFile;
}
@Override
File getProfileOwnerFileWithTestOverride(int userId) {
return new File(mDeviceOwnerFile.getAbsoluteFile() + "-" + userId);
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
mDataDir = new File(getContext().getCacheDir(), "OwnersTest");
if (mDataDir.exists()) {
assertTrue("failed to delete dir", FileUtils.deleteContents(mDataDir));
}
mDataDir.mkdirs();
Log.i(TAG, "Created " + mDataDir);
}
private String readAsset(String assetPath) throws IOException {
final StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(
new InputStreamReader((getContext().getResources().getAssets().open(assetPath))))) {
new InputStreamReader(
mRealTestContext.getResources().getAssets().open(assetPath)))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
@@ -126,7 +76,7 @@ public class OwnersTest extends DpmTestBase {
ui.id = userId;
userInfos.add(ui);
}
when(getContext().getMockUserManager().getUsers()).thenReturn(userInfos);
when(getContext().userManager.getUsers()).thenReturn(userInfos);
}
public void testUpgrade01() throws Exception {
@@ -134,9 +84,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test01/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test01/input.xml"));
owners.load();
@@ -160,7 +111,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -176,9 +127,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test02/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test02/input.xml"));
owners.load();
@@ -204,7 +156,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertTrue(owners.hasDeviceOwner());
@@ -223,9 +175,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test03/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test03/input.xml"));
owners.load();
@@ -259,7 +212,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -286,9 +239,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test04/input.xml"));
owners.load();
@@ -327,7 +281,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertTrue(owners.hasDeviceOwner());
@@ -359,9 +313,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test05/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test05/input.xml"));
owners.load();
@@ -386,7 +341,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -405,9 +360,10 @@ public class OwnersTest extends DpmTestBase {
// First, migrate.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test06/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test06/input.xml"));
owners.load();
@@ -431,7 +387,7 @@ public class OwnersTest extends DpmTestBase {
// Then re-read and check.
{
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
owners.load();
assertFalse(owners.hasDeviceOwner());
@@ -447,10 +403,11 @@ public class OwnersTest extends DpmTestBase {
public void testRemoveExistingFiles() throws Exception {
addUsersToUserManager(10, 11, 20, 21);
final OwnersSub owners = new OwnersSub();
final OwnersTestable owners = new OwnersTestable(getContext(), dataDir);
// First, migrate to create new-style config files.
createLegacyFile(owners.mLegacyFile, readAsset("OwnersTest/test04/input.xml"));
createLegacyFile(owners.getLegacyConfigFileWithTestOverride(),
readAsset("OwnersTest/test04/input.xml"));
owners.load();