DO NOT MERGE: Fixed NetworkPolicyManagerServiceTest.
NetworkPolicyManagerServiceTest had many tests there were @Suppressed
because they were obsolete and harder to fix using Easymocks.
This CL replaced EasyMock by Mockito and re-enabled most tests, although
some tests were removed because:
- It's underlying logic changed too much that.
- It would be hard to mock all external entities they interact with.
- They are covered by CTS tests.
Bug: 30764608
Test: runtest --path
frameworks/base/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
(cherry picked from commit I53ff86fc9b64cb058846f1aefa244771630d9e1e)
Change-Id: Ia9cdb780cb0917477b310dc38d2e39731d6a7609
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 4405c1b..97f913e 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,7 +49,6 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
-import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.IMaintenanceActivityListener;
import android.os.Looper;
@@ -1238,7 +1237,7 @@
}
}
- public final class LocalService {
+ public class LocalService {
public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
String reason) {
addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 8d36ac9..d890444 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,17 +16,12 @@
package com.android.server;
-import static android.content.Intent.ACTION_UID_REMOVED;
-import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
-import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
import static android.net.TrafficStats.KB_IN_BYTES;
@@ -34,28 +29,36 @@
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.Time.TIMEZONE_UTC;
+
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
-import static org.easymock.EasyMock.anyInt;
-import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.aryEq;
-import static org.easymock.EasyMock.capture;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.isA;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
-import android.app.IProcessObserver;
+import android.app.IUidObserver;
import android.app.Notification;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
-import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
@@ -69,39 +72,40 @@
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.MessageQueue.IdleHandler;
+import android.os.PowerManagerInternal;
import android.os.UserHandle;
import android.test.AndroidTestCase;
-import android.test.mock.MockPackageManager;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
import android.text.format.Time;
+import android.util.Log;
import android.util.TrustedTime;
import com.android.internal.util.test.BroadcastInterceptingContext;
+import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkPolicyManagerService;
+
+import libcore.io.IoUtils;
+
import com.google.common.util.concurrent.AbstractFuture;
-import org.easymock.Capture;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
import java.io.File;
-import java.util.Calendar;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
-import java.util.TimeZone;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.logging.Handler;
-
-import libcore.io.IoUtils;
/**
* Tests for {@link NetworkPolicyManagerService}.
*/
-@LargeTest
public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
private static final String TAG = "NetworkPolicyManagerServiceTest";
@@ -113,20 +117,22 @@
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
+ private List<Class<?>> mLocalServices = new ArrayList<>();
- private IActivityManager mActivityManager;
- private INetworkStatsService mStatsService;
- private INetworkManagementService mNetworkManager;
- private INetworkPolicyListener mPolicyListener;
- private TrustedTime mTime;
- private IConnectivityManager mConnManager;
- private INotificationManager mNotifManager;
+ private @Mock IActivityManager mActivityManager;
+ private @Mock INetworkStatsService mStatsService;
+ private @Mock INetworkManagementService mNetworkManager;
+ private @Mock TrustedTime mTime;
+ private @Mock IConnectivityManager mConnManager;
+ private @Mock INotificationManager mNotifManager;
+ private @Mock UsageStatsManagerInternal mUsageStats;
+ private @Mock PackageManager mPackageManager;
- private NetworkPolicyManagerService mService;
- private IProcessObserver mProcessObserver;
+ private IUidObserver mUidObserver;
private INetworkManagementEventObserver mNetworkObserver;
- private Binder mStubBinder = new Binder();
+ private NetworkPolicyListenerAnswer mPolicyListener;
+ private NetworkPolicyManagerService mService;
private long mStartTime;
private long mElapsedRealtime;
@@ -139,39 +145,22 @@
private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
- private static final int PID_1 = 400;
- private static final int PID_2 = 401;
- private static final int PID_3 = 402;
+ private static final String PKG_NAME_A = "name.is.A,pkg.A";
- public void _setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
+ MockitoAnnotations.initMocks(this);
+
+ final Context context = getContext();
+
setCurrentTimeMillis(TEST_START);
// intercept various broadcasts, and pretend that uids have packages
- mServiceContext = new BroadcastInterceptingContext(getContext()) {
+ mServiceContext = new BroadcastInterceptingContext(context) {
@Override
public PackageManager getPackageManager() {
- return new MockPackageManager() {
- @Override
- public String[] getPackagesForUid(int uid) {
- return new String[] { "com.example" };
- }
-
- @Override
- public PackageInfo getPackageInfo(String packageName, int flags) {
- final PackageInfo info = new PackageInfo();
- final Signature signature;
- if ("android".equals(packageName)) {
- signature = new Signature("F00D");
- } else {
- signature = new Signature("DEAD");
- }
- info.signatures = new Signature[] { signature };
- return info;
- }
-
- };
+ return mPackageManager;
}
@Override
@@ -180,54 +169,69 @@
}
};
- mPolicyDir = getContext().getFilesDir();
+ mPolicyDir = context.getFilesDir();
if (mPolicyDir.exists()) {
IoUtils.deleteContents(mPolicyDir);
}
- mActivityManager = createMock(IActivityManager.class);
- mStatsService = createMock(INetworkStatsService.class);
- mNetworkManager = createMock(INetworkManagementService.class);
- mPolicyListener = createMock(INetworkPolicyListener.class);
- mTime = createMock(TrustedTime.class);
- mConnManager = createMock(IConnectivityManager.class);
- mNotifManager = createMock(INotificationManager.class);
+ doAnswer(new Answer<Void>() {
- mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
- mStatsService, mNetworkManager, mTime, mPolicyDir, true);
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mUidObserver = (IUidObserver) invocation.getArguments()[0];
+ Log.d(TAG, "set mUidObserver to " + mUidObserver);
+ return null;
+ }
+ }).when(mActivityManager).registerUidObserver(any(), anyInt());
+
+ addLocalServiceMock(PowerManagerInternal.class);
+ addLocalServiceMock(DeviceIdleController.LocalService.class);
+ addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStats);
+
+ mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
+ mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
+ mPolicyListener = new NetworkPolicyListenerAnswer(mService);
- // RemoteCallbackList needs a binder to use as key
- expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
- replay();
- mService.registerListener(mPolicyListener);
- verifyAndReset();
+ // Sets some common expectations.
+ when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
+ new Answer<PackageInfo>() {
- // catch IProcessObserver during systemReady()
- final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
- mActivityManager.registerProcessObserver(capture(processObserver));
- expectLastCall().atLeastOnce();
-
- // catch INetworkManagementEventObserver during systemReady()
- final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
- INetworkManagementEventObserver>();
- mNetworkManager.registerObserver(capture(networkObserver));
- expectLastCall().atLeastOnce();
-
- expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+ @Override
+ public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
+ final String packageName = (String) invocation.getArguments()[0];
+ final PackageInfo info = new PackageInfo();
+ final Signature signature;
+ if ("android".equals(packageName)) {
+ signature = new Signature("F00D");
+ } else {
+ signature = new Signature("DEAD");
+ }
+ info.signatures = new Signature[] {
+ signature
+ };
+ return info;
+ }
+ });
+ when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(new ApplicationInfo());
+ when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
+ when(mUsageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
+ when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
expectCurrentTime();
- replay();
+ // Prepare NPMS.
mService.systemReady();
- verifyAndReset();
- mProcessObserver = processObserver.getValue();
+ // catch INetworkManagementEventObserver during systemReady()
+ ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
-
}
- public void _tearDown() throws Exception {
+ public void tearDown() throws Exception {
for (File file : mPolicyDir.listFiles()) {
file.delete();
}
@@ -237,170 +241,51 @@
mActivityManager = null;
mStatsService = null;
- mPolicyListener = null;
mTime = null;
mService = null;
- mProcessObserver = null;
+
+ // TODO: must remove services, otherwise next test will fail.
+ // JUnit4 would avoid that hack by using a static setup.
+ removeLocalServiceMocks();
+
+ // Added by NetworkPolicyManagerService's constructor.
+ LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
super.tearDown();
}
- @Suppress
- public void testPolicyChangeTriggersBroadcast() throws Exception {
+ // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
+ // don't check for side-effects (like calls to NetworkManagementService) neither cover all
+ // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
+ // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
+
+ public void testPolicyChangeTriggersListener() throws Exception {
+ mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
+
mService.setUidPolicy(APP_ID_A, POLICY_NONE);
-
- // change background policy and expect broadcast
- final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
- ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-
mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- backgroundChanged.get();
+ mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
}
- @Suppress
- public void testPidForegroundCombined() throws Exception {
- IdleFuture idle;
-
- // push all uid into background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
- idle.get();
+ public void testUidForeground() throws Exception {
+ // push all uids into background
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
- // push one of the shared pids into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
+ // push one of the uids into foreground
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
- idle.get();
+ mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
+ mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
-
- // push both pid into foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull one out, should still be foreground
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- idle.get();
- assertTrue(mService.isUidForeground(UID_A));
-
- // pull final pid out, should now be background
- idle = expectIdle();
- mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- idle.get();
- assertFalse(mService.isUidForeground(UID_A));
- }
-
- @Suppress
- public void testPolicyNone() throws Exception {
- Future<Void> future;
-
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // POLICY_NONE should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyReject() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_ALLOW in foreground
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, true);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
- future.get();
- verifyAndReset();
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
- public void testPolicyRejectAddRemove() throws Exception {
- Future<Void> future;
-
- // POLICY_NONE should have RULE_ALLOW in background
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
-
- // adding POLICY_REJECT should cause RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // removing POLICY_REJECT should return us to RULE_ALLOW
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_NONE);
- future.get();
- verifyAndReset();
}
public void testLastCycleBoundaryThisMonth() throws Exception {
@@ -545,11 +430,9 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Suppress
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -560,75 +443,39 @@
// first, pretend that wifi network comes online. no policy active,
// which means we shouldn't push limit to interface.
state = new NetworkState[] { buildWifi() };
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
// now change cycle to be on 15th, and test in early march, to verify we
// pick cycle day in previous month.
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
expectCurrentTime();
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+ .thenReturn(stats.getTotalBytes());
- // TODO: consider making strongly ordered mock
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ // TODO: consider making strongly ordered mock
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
}
- @Suppress
- public void testUidRemovedPolicyCleared() throws Exception {
- Future<Void> future;
-
- // POLICY_REJECT should RULE_REJECT in background
- expectSetUidMeteredNetworkBlacklist(UID_A, true);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
- replay();
- mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- future.get();
- verifyAndReset();
-
- // uninstall should clear RULE_REJECT
- expectSetUidMeteredNetworkBlacklist(UID_A, false);
- expectSetUidForeground(UID_A, false);
- future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
- replay();
- final Intent intent = new Intent(ACTION_UID_REMOVED);
- intent.putExtra(EXTRA_UID, UID_A);
- mServiceContext.sendBroadcast(intent);
- future.get();
- verifyAndReset();
- }
-
- @Suppress
public void testOverWarningLimitNotification() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
+ Future<String> tagFuture = null;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -643,20 +490,15 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged();
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
* MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
// bring up wifi network
@@ -667,22 +509,17 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
}
// go over warning, which should kick notification
@@ -692,18 +529,15 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_WARNING, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+
}
// go over limit, which should kick notification and dialog
@@ -713,18 +547,14 @@
{
expectCurrentTime();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, false);
-
- expectForceUpdate();
- expectClearNotifications();
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
+
assertNotificationType(TYPE_LIMIT, tagFuture.get());
- verifyAndReset();
+ verifyPolicyDataEnable(TYPE_WIFI, false);
}
// now snooze policy, which should remove quota
@@ -732,35 +562,27 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
-
- // snoozed interface still has high quota so background data is
- // still restricted.
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
- expectAdvisePersistThreshold();
- expectMeteredIfacesChanged(TEST_IFACE);
-
- future = expectClearNotifications();
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
tagFuture = expectEnqueueNotification();
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
mService.snoozeLimit(sTemplateWifi);
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
- future.get();
- verifyAndReset();
+ // snoozed interface still has high quota so background data is
+ // still restricted.
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+ verifyPolicyDataEnable(TYPE_WIFI, true);
}
}
- @Suppress
public void testMeteredNetworkWithoutLimit() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<Void> future;
- Future<String> tagFuture;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -775,24 +597,19 @@
{
expectCurrentTime();
- expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
- expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
- .andReturn(stats.getTotalBytes()).atLeastOnce();
- expectPolicyDataEnable(TYPE_WIFI, true);
+ when(mConnManager.getAllNetworkState()).thenReturn(state);
+ when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
+ currentTimeMillis())).thenReturn(stats.getTotalBytes());
- expectRemoveInterfaceQuota(TEST_IFACE);
- expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
-
- expectClearNotifications();
- expectAdvisePersistThreshold();
- future = expectMeteredIfacesChanged(TEST_IFACE);
-
- replay();
+ mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
true));
- future.get();
- verifyAndReset();
+ mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+
+ verifyPolicyDataEnable(TYPE_WIFI, true);
+ verifyRemoveInterfaceQuota(TEST_IFACE);
+ verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
}
}
@@ -815,87 +632,36 @@
}
private void expectCurrentTime() throws Exception {
- expect(mTime.forceRefresh()).andReturn(false).anyTimes();
- expect(mTime.hasCache()).andReturn(true).anyTimes();
- expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
- expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
- expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
- }
-
- private void expectForceUpdate() throws Exception {
- mStatsService.forceUpdate();
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectClearNotifications() throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mNotifManager.cancelNotificationWithTag(
- isA(String.class), isA(String.class), anyInt(), anyInt());
- expectLastCall().andAnswer(future).anyTimes();
- return future;
+ when(mTime.forceRefresh()).thenReturn(false);
+ when(mTime.hasCache()).thenReturn(true);
+ when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
+ when(mTime.getCacheAge()).thenReturn(0L);
+ when(mTime.getCacheCertainty()).thenReturn(0L);
}
private Future<String> expectEnqueueNotification() throws Exception {
- final FutureCapture<String> tag = new FutureCapture<String>();
- mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
- capture(tag.capture), anyInt(),
- isA(Notification.class), isA(int[].class), UserHandle.myUserId());
- return tag;
+ final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
+ doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
+ anyString(), anyString(), anyString() /* capture here (index 2)*/,
+ anyInt(), isA(Notification.class), isA(int[].class), anyInt());
+ return futureAnswer;
}
- private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
- mNetworkManager.setInterfaceQuota(iface, quotaBytes);
- expectLastCall().atLeastOnce();
+ private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
}
- private void expectRemoveInterfaceQuota(String iface) throws Exception {
- mNetworkManager.removeInterfaceQuota(iface);
- expectLastCall().atLeastOnce();
+ private void verifyRemoveInterfaceQuota(String iface) throws Exception {
+ verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
}
- private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
- mNetworkManager.setInterfaceAlert(iface, alertBytes);
- expectLastCall().atLeastOnce();
- }
-
- private void expectRemoveInterfaceAlert(String iface) throws Exception {
- mNetworkManager.removeInterfaceAlert(iface);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
- throws Exception {
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
- expectLastCall().atLeastOnce();
- }
-
- private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
- mStatsService.setUidForeground(uid, uidForeground);
- expectLastCall().atLeastOnce();
- }
-
- private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
- final FutureAnswer future = new FutureAnswer();
- mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
- expectLastCall().andAnswer(future);
- return future;
- }
-
- private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
+ private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
// TODO: bring back this test
return null;
}
- private void expectAdvisePersistThreshold() throws Exception {
- mStatsService.advisePersistThreshold(anyLong());
- expectLastCall().anyTimes();
+ private void verifyAdvisePersistThreshold() throws Exception {
+ verify(mStatsService).advisePersistThreshold(anyLong());
}
private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -909,50 +675,21 @@
}
}
- private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
+ private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
+ private final int index;
+
+ FutureAnswer(int index) {
+ this.index = index;
+ }
@Override
- public Void answer() {
- set(null);
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ @SuppressWarnings("unchecked")
+ T captured = (T) invocation.getArguments()[index];
+ set(captured);
return null;
}
}
- private static class FutureCapture<T> extends TestAbstractFuture<T> {
- public Capture<T> capture = new Capture<T>() {
- @Override
- public void setValue(T value) {
- super.setValue(value);
- set(value);
- }
- };
- }
-
- private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
- @Override
- public Void get() throws InterruptedException, ExecutionException {
- try {
- return get(5, TimeUnit.SECONDS);
- } catch (TimeoutException e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public boolean queueIdle() {
- set(null);
- return false;
- }
- }
-
- /**
- * Wait until {@link #mService} internal {@link Handler} is idle.
- */
- private IdleFuture expectIdle() {
- final IdleFuture future = new IdleFuture();
- mService.addIdleHandler(future);
- return future;
- }
-
private static void assertTimeEquals(long expected, long actual) {
if (expected != actual) {
fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -980,7 +717,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals(
+ assertEquals("notification type mismatch for '" + actualTag +"'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1001,15 +738,78 @@
mElapsedRealtime += duration;
}
- private void replay() {
- EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
+ /**
+ * Creates a mock and registers it to {@link LocalServices}.
+ */
+ private <T> T addLocalServiceMock(Class<T> clazz) {
+ final T mock = mock(clazz);
+ return addLocalServiceMock(clazz, mock);
}
- private void verifyAndReset() {
- EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
- EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
- mConnManager, mNotifManager);
+ /**
+ * Registers a mock to {@link LocalServices}.
+ */
+ private <T> T addLocalServiceMock(Class<T> clazz, T mock) {
+ LocalServices.addService(clazz, mock);
+ mLocalServices.add(clazz);
+ return mock;
+ }
+
+ /**
+ * Unregisters all mocks from {@link LocalServices}.
+ */
+ private void removeLocalServiceMocks() {
+ for (Class<?> clazz : mLocalServices) {
+ Log.d(TAG, "removeLocalServiceMock(): " + clazz.getName());
+ LocalServices.removeServiceForTest(clazz);
+ }
+ mLocalServices.clear();
+ }
+
+ /**
+ * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
+ *
+ * <p>Typical usage:
+ * <pre><code>
+ * mPolicyListener.expect().someCallback(any());
+ * // do something on objects under test
+ * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
+ * </code></pre>
+ */
+ final class NetworkPolicyListenerAnswer implements Answer<Void> {
+ private CountDownLatch latch;
+ private final INetworkPolicyListener listener;
+
+ NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
+ this.listener = mock(INetworkPolicyListener.class);
+ // RemoteCallbackList needs a binder to use as key
+ when(listener.asBinder()).thenReturn(new Binder());
+ service.registerListener(listener);
+ }
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Log.d(TAG,"counting down on answer: " + invocation);
+ latch.countDown();
+ return null;
+ }
+
+ INetworkPolicyListener expect() {
+ assertNull("expect() called before waitAndVerify()", latch);
+ latch = new CountDownLatch(1);
+ return doAnswer(this).when(listener);
+ }
+
+ INetworkPolicyListener waitAndVerify() {
+ assertNotNull("waitAndVerify() called before expect()", latch);
+ try {
+ assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
+ } catch (InterruptedException e) {
+ fail("Thread interrupted before callback called");
+ } finally {
+ latch = null;
+ }
+ return verify(listener, atLeastOnce());
+ }
}
}