summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CoreTests/android/core/HeapTest.java476
-rw-r--r--tests/ServiceCrashTest/Android.mk19
-rw-r--r--tests/ServiceCrashTest/AndroidManifest.xml23
-rw-r--r--tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/CrashingService.java66
-rw-r--r--tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/MainActivity.java70
-rw-r--r--tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/ServiceCrashTest.java76
-rw-r--r--tests/net/Android.mk1
-rw-r--r--tests/net/OWNERS3
-rw-r--r--tests/net/java/android/net/IpSecManagerTest.java225
-rw-r--r--tests/net/java/android/net/NetworkStatsHistoryTest.java15
-rw-r--r--tests/net/java/android/net/apf/ApfTest.java97
-rw-r--r--tests/net/java/android/net/ip/IpReachabilityMonitorTest.java59
-rw-r--r--tests/net/java/android/net/netlink/ConntrackMessageTest.java131
-rw-r--r--tests/net/java/android/net/nsd/NsdManagerTest.java30
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java73
-rw-r--r--tests/net/java/com/android/server/IpSecServiceTest.java435
-rw-r--r--tests/net/java/com/android/server/NetworkManagementServiceTest.java254
-rw-r--r--tests/net/java/com/android/server/NsdServiceTest.java5
-rw-r--r--tests/net/java/com/android/server/connectivity/Nat464XlatTest.java226
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java75
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java346
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java60
22 files changed, 2213 insertions, 552 deletions
diff --git a/tests/CoreTests/android/core/HeapTest.java b/tests/CoreTests/android/core/HeapTest.java
deleted file mode 100644
index 400d0412c58e..000000000000
--- a/tests/CoreTests/android/core/HeapTest.java
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.core;
-
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-import android.test.suitebuilder.annotation.Suppress;
-import dalvik.system.VMRuntime;
-import junit.framework.TestCase;
-
-import java.lang.ref.PhantomReference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
-import java.util.LinkedList;
-import java.util.Random;
-
-
-public class HeapTest extends TestCase {
-
- private static final String TAG = "HeapTest";
-
- /**
- * Returns a WeakReference to an object that has no
- * other references. This is done in a separate method
- * to ensure that the Object's address isn't sitting in
- * a stale local register.
- */
- private WeakReference<Object> newRef() {
- return new WeakReference<Object>(new Object());
- }
-
- private static void makeRefs(Object objects[], SoftReference<Object> refs[]) {
- for (int i = 0; i < objects.length; i++) {
- objects[i] = (Object) new byte[8 * 1024];
- refs[i] = new SoftReference<Object>(objects[i]);
- }
- }
-
- private static <T> int checkRefs(SoftReference<T> refs[], int last) {
- int i;
- int numCleared = 0;
- for (i = 0; i < refs.length; i++) {
- Object o = refs[i].get();
- if (o == null) {
- numCleared++;
- }
- }
- if (numCleared != last) {
- Log.i(TAG, "****** " + numCleared + "/" + i + " cleared ******");
- }
- return numCleared;
- }
-
- private static void clearRefs(Object objects[], int skip) {
- for (int i = 0; i < objects.length; i += skip) {
- objects[i] = null;
- }
- }
-
- private static void clearRefs(Object objects[]) {
- clearRefs(objects, 1);
- }
-
- private static <T> void checkRefs(T objects[], SoftReference<T> refs[]) {
- boolean ok = true;
-
- for (int i = 0; i < objects.length; i++) {
- if (refs[i].get() != objects[i]) {
- ok = false;
- }
- }
- if (!ok) {
- throw new RuntimeException("Test failed: soft refs not cleared");
- }
- }
-
- @MediumTest
- public void testGcSoftRefs() throws Exception {
- final int NUM_REFS = 128;
-
- Object objects[] = new Object[NUM_REFS];
- SoftReference<Object> refs[] = new SoftReference[objects.length];
-
- /* Create a bunch of objects and a parallel array
- * of SoftReferences.
- */
- makeRefs(objects, refs);
- Runtime.getRuntime().gc();
-
- /* Let go of some of the hard references to the objects so that
- * the references can be cleared.
- */
- clearRefs(objects, 3);
-
- /* Collect all softly-reachable objects.
- */
- VMRuntime.getRuntime().gcSoftReferences();
- Runtime.getRuntime().runFinalization();
-
- /* Make sure that the objects were collected.
- */
- checkRefs(objects, refs);
-
- /* Remove more hard references and re-check.
- */
- clearRefs(objects, 2);
- VMRuntime.getRuntime().gcSoftReferences();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs);
-
- /* Remove the rest of the references and re-check.
- */
- /* Remove more hard references and re-check.
- */
- clearRefs(objects);
- VMRuntime.getRuntime().gcSoftReferences();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs);
- }
-
- public void xxtestSoftRefPartialClean() throws Exception {
- final int NUM_REFS = 128;
-
- Object objects[] = new Object[NUM_REFS];
- SoftReference<Object> refs[] = new SoftReference[objects.length];
-
- /* Create a bunch of objects and a parallel array
- * of SoftReferences.
- */
- makeRefs(objects, refs);
- Runtime.getRuntime().gc();
-
- /* Let go of the hard references to the objects so that
- * the references can be cleared.
- */
- clearRefs(objects);
-
- /* Start creating a bunch of temporary and permanent objects
- * to drive GC.
- */
- final int NUM_OBJECTS = 64 * 1024;
- Object junk[] = new Object[NUM_OBJECTS];
- Random random = new Random();
-
- int i = 0;
- int mod = 0;
- int totalSize = 0;
- int cleared = -1;
- while (i < junk.length && totalSize < 8 * 1024 * 1024) {
- int r = random.nextInt(64 * 1024) + 128;
- Object o = (Object) new byte[r];
- if (++mod % 16 == 0) {
- junk[i++] = o;
- totalSize += r * 4;
- }
- cleared = checkRefs(refs, cleared);
- }
- }
-
- private static void makeRefs(Object objects[], WeakReference<Object> refs[]) {
- for (int i = 0; i < objects.length; i++) {
- objects[i] = new Object();
- refs[i] = new WeakReference<Object>(objects[i]);
- }
- }
-
- private static <T> void checkRefs(T objects[], WeakReference<T> refs[]) {
- boolean ok = true;
-
- for (int i = 0; i < objects.length; i++) {
- if (refs[i].get() != objects[i]) {
- ok = false;
- }
- }
- if (!ok) {
- throw new RuntimeException("Test failed: " +
- "weak refs not cleared");
- }
- }
-
- @MediumTest
- public void testWeakRefs() throws Exception {
- final int NUM_REFS = 16;
-
- Object objects[] = new Object[NUM_REFS];
- WeakReference<Object> refs[] = new WeakReference[objects.length];
-
- /* Create a bunch of objects and a parallel array
- * of WeakReferences.
- */
- makeRefs(objects, refs);
- Runtime.getRuntime().gc();
- checkRefs(objects, refs);
-
- /* Clear out every other strong reference.
- */
- for (int i = 0; i < objects.length; i += 2) {
- objects[i] = null;
- }
- Runtime.getRuntime().gc();
- checkRefs(objects, refs);
-
- /* Clear out the rest of them.
- */
- for (int i = 0; i < objects.length; i++) {
- objects[i] = null;
- }
- Runtime.getRuntime().gc();
- checkRefs(objects, refs);
- }
-
- private static void makeRefs(Object objects[], PhantomReference<Object> refs[],
- ReferenceQueue<Object> queue) {
- for (int i = 0; i < objects.length; i++) {
- objects[i] = new Object();
- refs[i] = new PhantomReference<Object>(objects[i], queue);
- }
- }
-
- static <T> void checkRefs(T objects[], PhantomReference<T> refs[],
- ReferenceQueue<T> queue) {
- boolean ok = true;
-
- /* Make sure that the reference that should be on
- * the queue are marked as enqueued. Once we
- * pull them off the queue, they will no longer
- * be marked as enqueued.
- */
- for (int i = 0; i < objects.length; i++) {
- if (objects[i] == null && refs[i] != null) {
- if (!refs[i].isEnqueued()) {
- ok = false;
- }
- }
- }
- if (!ok) {
- throw new RuntimeException("Test failed: " +
- "phantom refs not marked as enqueued");
- }
-
- /* Make sure that all of the references on the queue
- * are supposed to be there.
- */
- PhantomReference<T> ref;
- while ((ref = (PhantomReference<T>) queue.poll()) != null) {
- /* Find the list index that corresponds to this reference.
- */
- int i;
- for (i = 0; i < objects.length; i++) {
- if (refs[i] == ref) {
- break;
- }
- }
- if (i == objects.length) {
- throw new RuntimeException("Test failed: " +
- "unexpected ref on queue");
- }
- if (objects[i] != null) {
- throw new RuntimeException("Test failed: " +
- "reference enqueued for strongly-reachable " +
- "object");
- }
- refs[i] = null;
-
- /* TODO: clear doesn't do much, since we're losing the
- * strong ref to the ref object anyway. move the ref
- * into another list.
- */
- ref.clear();
- }
-
- /* We've visited all of the enqueued references.
- * Make sure that there aren't any other references
- * that should have been enqueued.
- *
- * NOTE: there is a race condition here; this assumes
- * that the VM has serviced all outstanding reference
- * enqueue() calls.
- */
- for (int i = 0; i < objects.length; i++) {
- if (objects[i] == null && refs[i] != null) {
-// System.out.println("HeapTest/PhantomRefs: refs[" + i +
-// "] should be enqueued");
- ok = false;
- }
- }
- if (!ok) {
- throw new RuntimeException("Test failed: " +
- "phantom refs not enqueued");
- }
- }
-
- @MediumTest
- public void testPhantomRefs() throws Exception {
- final int NUM_REFS = 16;
-
- Object objects[] = new Object[NUM_REFS];
- PhantomReference<Object> refs[] = new PhantomReference[objects.length];
- ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
-
- /* Create a bunch of objects and a parallel array
- * of PhantomReferences.
- */
- makeRefs(objects, refs, queue);
- Runtime.getRuntime().gc();
- checkRefs(objects, refs, queue);
-
- /* Clear out every other strong reference.
- */
- for (int i = 0; i < objects.length; i += 2) {
- objects[i] = null;
- }
- // System.out.println("HeapTest/PhantomRefs: cleared evens");
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs, queue);
-
- /* Clear out the rest of them.
- */
- for (int i = 0; i < objects.length; i++) {
- objects[i] = null;
- }
- // System.out.println("HeapTest/PhantomRefs: cleared all");
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs, queue);
- }
-
- private static int sNumFinalized = 0;
- private static final Object sLock = new Object();
-
- private static class FinalizableObject {
- protected void finalize() {
- // System.out.println("gc from finalize()");
- Runtime.getRuntime().gc();
- synchronized (sLock) {
- sNumFinalized++;
- }
- }
- }
-
- private static void makeRefs(FinalizableObject objects[],
- WeakReference<FinalizableObject> refs[]) {
- for (int i = 0; i < objects.length; i++) {
- objects[i] = new FinalizableObject();
- refs[i] = new WeakReference<FinalizableObject>(objects[i]);
- }
- }
-
- @LargeTest
- public void testWeakRefsAndFinalizers() throws Exception {
- final int NUM_REFS = 16;
-
- FinalizableObject objects[] = new FinalizableObject[NUM_REFS];
- WeakReference<FinalizableObject> refs[] = new WeakReference[objects.length];
- int numCleared;
-
- /* Create a bunch of objects and a parallel array
- * of WeakReferences.
- */
- makeRefs(objects, refs);
- Runtime.getRuntime().gc();
- checkRefs(objects, refs);
-
- /* Clear out every other strong reference.
- */
- sNumFinalized = 0;
- numCleared = 0;
- for (int i = 0; i < objects.length; i += 2) {
- objects[i] = null;
- numCleared++;
- }
- // System.out.println("HeapTest/WeakRefsAndFinalizers: cleared evens");
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs);
- if (sNumFinalized != numCleared) {
- throw new RuntimeException("Test failed: " +
- "expected " + numCleared + " finalizations, saw " +
- sNumFinalized);
- }
-
- /* Clear out the rest of them.
- */
- sNumFinalized = 0;
- numCleared = 0;
- for (int i = 0; i < objects.length; i++) {
- if (objects[i] != null) {
- objects[i] = null;
- numCleared++;
- }
- }
- // System.out.println("HeapTest/WeakRefsAndFinalizers: cleared all");
- Runtime.getRuntime().gc();
- Runtime.getRuntime().runFinalization();
- checkRefs(objects, refs);
- if (sNumFinalized != numCleared) {
- throw new RuntimeException("Test failed: " +
- "expected " + numCleared + " finalizations, saw " +
- sNumFinalized);
- }
- }
-
- // TODO: flaky test
- //@MediumTest
- public void testOomeLarge() throws Exception {
- /* Just shy of the typical max heap size so that it will actually
- * try to allocate it instead of short-circuiting.
- */
- final int SIXTEEN_MB = (16 * 1024 * 1024 - 32);
-
- Boolean sawEx = false;
- byte a[];
-
- try {
- a = new byte[SIXTEEN_MB];
- } catch (OutOfMemoryError oom) {
- //Log.i(TAG, "HeapTest/OomeLarge caught " + oom);
- sawEx = true;
- }
-
- if (!sawEx) {
- throw new RuntimeException("Test failed: " +
- "OutOfMemoryError not thrown");
- }
- }
-
- //See bug 1308253 for reasons.
- @Suppress
- public void disableTestOomeSmall() throws Exception {
- final int SIXTEEN_MB = (16 * 1024 * 1024);
- final int LINK_SIZE = 6 * 4; // estimated size of a LinkedList's node
-
- Boolean sawEx = false;
-
- LinkedList<Object> list = new LinkedList<Object>();
-
- /* Allocate progressively smaller objects to fill up the entire heap.
- */
- int objSize = 1 * 1024 * 1024;
- while (objSize >= LINK_SIZE) {
- try {
- for (int i = 0; i < SIXTEEN_MB / objSize; i++) {
- list.add((Object)new byte[objSize]);
- }
- } catch (OutOfMemoryError oom) {
- sawEx = true;
- }
-
- if (!sawEx) {
- throw new RuntimeException("Test failed: " +
- "OutOfMemoryError not thrown while filling heap");
- }
- sawEx = false;
-
- objSize = (objSize * 4) / 5;
- }
- }
-}
diff --git a/tests/ServiceCrashTest/Android.mk b/tests/ServiceCrashTest/Android.mk
new file mode 100644
index 000000000000..d1f845623be8
--- /dev/null
+++ b/tests/ServiceCrashTest/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := ServiceCrashTest
+
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := legacy-android-test
+
+LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/ServiceCrashTest/AndroidManifest.xml b/tests/ServiceCrashTest/AndroidManifest.xml
new file mode 100644
index 000000000000..387c8b8ae36b
--- /dev/null
+++ b/tests/ServiceCrashTest/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.servicecrashtest">
+
+ <application android:label="Service Crash Test">
+ <uses-library android:name="android.test.runner" />
+
+ <service android:name=".CrashingService"
+ android:process=":badservice" />
+
+ <activity android:name=".MainActivity" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:label="Test bound service crash restart"
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.tests.servicecrashtest" />
+
+</manifest>
diff --git a/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/CrashingService.java b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/CrashingService.java
new file mode 100644
index 000000000000..8593bcea9c3d
--- /dev/null
+++ b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/CrashingService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 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.tests.servicecrashtest;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.widget.Toast;
+
+public class CrashingService extends Service {
+ private ServiceHandler mServiceHandler;
+
+ static long CRASH_DELAY = 1000;
+
+ // Handler that receives messages from the thread
+ private final class ServiceHandler extends Handler {
+ public ServiceHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ throw new RuntimeException("Crashing!");
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ mServiceHandler = new ServiceHandler(Looper.getMainLooper());
+ Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+
+ Message msg = mServiceHandler.obtainMessage();
+ mServiceHandler.sendMessageDelayed(msg, CRASH_DELAY);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ // If we get killed, after returning from here, restart
+ return START_STICKY;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // We don't provide binding, so return null
+ return null;
+ }
+} \ No newline at end of file
diff --git a/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/MainActivity.java b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/MainActivity.java
new file mode 100644
index 000000000000..8fffecc41dbd
--- /dev/null
+++ b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/MainActivity.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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.tests.servicecrashtest;
+
+import android.app.Activity;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.TextView;
+
+import java.util.concurrent.CountDownLatch;
+
+public class MainActivity extends Activity {
+
+ private static final String TAG = "ServiceCrashTest";
+
+ static final CountDownLatch sBindingDiedLatch = new CountDownLatch(1);
+
+ private ServiceConnection mServiceConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.i(TAG, "Service connected");
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.i(TAG, "Service disconnected");
+ }
+
+ @Override
+ public void onBindingDied(ComponentName componentName) {
+ Log.i(TAG, "Binding died");
+ sBindingDiedLatch.countDown();
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstance) {
+ super.onCreate(savedInstance);
+
+ setContentView(new TextView(this));
+ }
+
+ public void onResume() {
+ Intent intent = new Intent();
+ intent.setClass(this, CrashingService.class);
+ bindService(intent, mServiceConnection, Service.BIND_AUTO_CREATE);
+
+ super.onResume();
+ }
+}
diff --git a/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/ServiceCrashTest.java b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/ServiceCrashTest.java
new file mode 100644
index 000000000000..fb0fa4b86185
--- /dev/null
+++ b/tests/ServiceCrashTest/src/com/android/tests/servicecrashtest/ServiceCrashTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 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.tests.servicecrashtest;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.test.InstrumentationTestCase;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+public class ServiceCrashTest extends InstrumentationTestCase {
+
+ private static final String TAG = ServiceCrashTest.class.getSimpleName();
+
+ private String mResetConstants = "foo=bar";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mResetConstants = Settings.Global.getString(
+ getInstrumentation().getContext().getContentResolver(),
+ Settings.Global.ACTIVITY_MANAGER_CONSTANTS);
+ setAMConstants("service_crash_restart_duration=5000,service_crash_max_retry=4");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Reset the activity manager constants
+ setAMConstants(mResetConstants);
+ super.tearDown();
+ }
+
+ private void setAMConstants(String value) throws IOException {
+ // Set the activity manager constants
+ if (value == null) {
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings delete global activity_manager_constants");
+ } else {
+ SystemUtil.runShellCommand(getInstrumentation(), "settings put global "
+ + "activity_manager_constants " + value);
+ }
+ }
+
+ public void testCrashQuickly() throws RemoteException {
+ Context ctx = getInstrumentation().getContext();
+ // Start the activity, which will bind the crashing service
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.setClass(ctx, MainActivity.class);
+ ctx.startActivity(intent);
+ try {
+ assertTrue(MainActivity.sBindingDiedLatch.await(200, TimeUnit.SECONDS));
+ } catch (InterruptedException ie) {
+ }
+ }
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index e4bf590d7586..677585cc0c0f 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -53,6 +53,7 @@ LOCAL_JNI_SHARED_LIBRARIES := libframeworksnettestsjni \
libtinyxml2 \
libvintf \
libhwbinder \
+ libunwindstack \
android.hidl.token@1.0
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
index fa269975d5e1..2d71c2013093 100644
--- a/tests/net/OWNERS
+++ b/tests/net/OWNERS
@@ -1,6 +1,9 @@
set noparent
per-file Android.mk = build.master@android.com
+per-file Android.mk = ek@google.com
+per-file Android.mk = hugobenichi@google.com
+per-file Android.mk = lorenzo@google.com
ek@google.com
hugobenichi@google.com
diff --git a/tests/net/java/android/net/IpSecManagerTest.java b/tests/net/java/android/net/IpSecManagerTest.java
new file mode 100644
index 000000000000..9f31d27508b2
--- /dev/null
+++ b/tests/net/java/android/net/IpSecManagerTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2017 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 android.net;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.system.Os;
+import android.test.AndroidTestCase;
+import com.android.server.IpSecService;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link IpSecManager}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class IpSecManagerTest {
+
+ private static final int TEST_UDP_ENCAP_PORT = 34567;
+ private static final int DROID_SPI = 0xD1201D;
+
+ private static final InetAddress GOOGLE_DNS_4;
+
+ static {
+ try {
+ // Google Public DNS Addresses;
+ GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
+ } catch (UnknownHostException e) {
+ throw new RuntimeException("Could not resolve DNS Addresses", e);
+ }
+ }
+
+ private IpSecService mMockIpSecService;
+ private IpSecManager mIpSecManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockIpSecService = mock(IpSecService.class);
+ mIpSecManager = new IpSecManager(mMockIpSecService);
+ }
+
+ /*
+ * Allocate a specific SPI
+ * Close SPIs
+ */
+ @Test
+ public void testAllocSpi() throws Exception {
+ int resourceId = 1;
+ IpSecSpiResponse spiResp =
+ new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+ when(mMockIpSecService.reserveSecurityParameterIndex(
+ eq(IpSecTransform.DIRECTION_IN),
+ eq(GOOGLE_DNS_4.getHostAddress()),
+ eq(DROID_SPI),
+ anyObject()))
+ .thenReturn(spiResp);
+
+ IpSecManager.SecurityParameterIndex droidSpi =
+ mIpSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_IN, GOOGLE_DNS_4, DROID_SPI);
+ assertEquals(DROID_SPI, droidSpi.getSpi());
+
+ droidSpi.close();
+
+ verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+ }
+
+ @Test
+ public void testAllocRandomSpi() throws Exception {
+ int resourceId = 1;
+ IpSecSpiResponse spiResp =
+ new IpSecSpiResponse(IpSecManager.Status.OK, resourceId, DROID_SPI);
+ when(mMockIpSecService.reserveSecurityParameterIndex(
+ eq(IpSecTransform.DIRECTION_OUT),
+ eq(GOOGLE_DNS_4.getHostAddress()),
+ eq(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX),
+ anyObject()))
+ .thenReturn(spiResp);
+
+ IpSecManager.SecurityParameterIndex randomSpi =
+ mIpSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+
+ assertEquals(DROID_SPI, randomSpi.getSpi());
+
+ randomSpi.close();
+
+ verify(mMockIpSecService).releaseSecurityParameterIndex(resourceId);
+ }
+
+ /*
+ * Throws resource unavailable exception
+ */
+ @Test
+ public void testAllocSpiResUnavaiableExeption() throws Exception {
+ IpSecSpiResponse spiResp =
+ new IpSecSpiResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE, 0, 0);
+ when(mMockIpSecService.reserveSecurityParameterIndex(
+ anyInt(), anyString(), anyInt(), anyObject()))
+ .thenReturn(spiResp);
+
+ try {
+ mIpSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+ fail("ResourceUnavailableException was not thrown");
+ } catch (IpSecManager.ResourceUnavailableException e) {
+ }
+ }
+
+ /*
+ * Throws spi unavailable exception
+ */
+ @Test
+ public void testAllocSpiSpiUnavaiableExeption() throws Exception {
+ IpSecSpiResponse spiResp = new IpSecSpiResponse(IpSecManager.Status.SPI_UNAVAILABLE, 0, 0);
+ when(mMockIpSecService.reserveSecurityParameterIndex(
+ anyInt(), anyString(), anyInt(), anyObject()))
+ .thenReturn(spiResp);
+
+ try {
+ mIpSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4);
+ fail("ResourceUnavailableException was not thrown");
+ } catch (IpSecManager.ResourceUnavailableException e) {
+ }
+ }
+
+ /*
+ * Should throw exception when request spi 0 in IpSecManager
+ */
+ @Test
+ public void testRequestAllocInvalidSpi() throws Exception {
+ try {
+ mIpSecManager.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, GOOGLE_DNS_4, 0);
+ fail("Able to allocate invalid spi");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testOpenEncapsulationSocket() throws Exception {
+ int resourceId = 1;
+ IpSecUdpEncapResponse udpEncapResp =
+ new IpSecUdpEncapResponse(
+ IpSecManager.Status.OK,
+ resourceId,
+ TEST_UDP_ENCAP_PORT,
+ Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
+ when(mMockIpSecService.openUdpEncapsulationSocket(eq(TEST_UDP_ENCAP_PORT), anyObject()))
+ .thenReturn(udpEncapResp);
+
+ IpSecManager.UdpEncapsulationSocket encapSocket =
+ mIpSecManager.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT);
+ assertNotNull(encapSocket.getSocket());
+ assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
+
+ encapSocket.close();
+
+ verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+ }
+
+ @Test
+ public void testOpenEncapsulationSocketOnRandomPort() throws Exception {
+ int resourceId = 1;
+ IpSecUdpEncapResponse udpEncapResp =
+ new IpSecUdpEncapResponse(
+ IpSecManager.Status.OK,
+ resourceId,
+ TEST_UDP_ENCAP_PORT,
+ Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP));
+
+ when(mMockIpSecService.openUdpEncapsulationSocket(eq(0), anyObject()))
+ .thenReturn(udpEncapResp);
+
+ IpSecManager.UdpEncapsulationSocket encapSocket =
+ mIpSecManager.openUdpEncapsulationSocket();
+
+ assertNotNull(encapSocket.getSocket());
+ assertEquals(TEST_UDP_ENCAP_PORT, encapSocket.getPort());
+
+ encapSocket.close();
+
+ verify(mMockIpSecService).closeUdpEncapsulationSocket(resourceId);
+ }
+
+ @Test
+ public void testOpenEncapsulationSocketWithInvalidPort() throws Exception {
+ try {
+ mIpSecManager.openUdpEncapsulationSocket(IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+ fail("IllegalArgumentException was not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ // TODO: add test when applicable transform builder interface is available
+}
diff --git a/tests/net/java/android/net/NetworkStatsHistoryTest.java b/tests/net/java/android/net/NetworkStatsHistoryTest.java
index e7b91b568d74..1c0c14eac08b 100644
--- a/tests/net/java/android/net/NetworkStatsHistoryTest.java
+++ b/tests/net/java/android/net/NetworkStatsHistoryTest.java
@@ -485,6 +485,21 @@ public class NetworkStatsHistoryTest extends AndroidTestCase {
assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1));
}
+ public void testSetValues() throws Exception {
+ stats = new NetworkStatsHistory(HOUR_IN_MILLIS);
+ stats.recordData(TEST_START, TEST_START + 1,
+ new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L));
+
+ assertEquals(1024L + 2048L, stats.getTotalBytes());
+
+ final NetworkStatsHistory.Entry entry = stats.getValues(0, null);
+ entry.rxBytes /= 2;
+ entry.txBytes *= 2;
+ stats.setValues(0, entry);
+
+ assertEquals(512L + 4096L, stats.getTotalBytes());
+ }
+
private static void assertIndexBeforeAfter(
NetworkStatsHistory stats, int before, int after, long time) {
assertEquals("unexpected before", before, stats.getIndexBefore(time));
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index bfbb8cc541d7..5008a4188905 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -614,9 +614,10 @@ public class ApfTest extends AndroidTestCase {
private final long mFixedTimeMs = SystemClock.elapsedRealtime();
public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
- boolean ieee802_3Filter, IpConnectivityLog log) throws Exception {
+ boolean ieee802_3Filter, int[] ethTypeBlackList,
+ IpConnectivityLog log) throws Exception {
super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
- ipManagerCallback, multicastFilter, ieee802_3Filter, log);
+ ipManagerCallback, multicastFilter, ieee802_3Filter, ethTypeBlackList, log);
}
// Pretend an RA packet has been received and show it to ApfFilter.
@@ -744,9 +745,10 @@ public class ApfTest extends AndroidTestCase {
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
+ final int[] ethTypeBlackList = {};
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -796,9 +798,10 @@ public class ApfTest extends AndroidTestCase {
@SmallTest
public void testApfFilterIPv6() throws Exception {
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
byte[] program = ipManagerCallback.getApfProgram();
// Verify empty IPv6 packet is passed
@@ -833,6 +836,7 @@ public class ApfTest extends AndroidTestCase {
final byte[] broadcastIpv4Addr = {(byte)192,0,2,(byte)255};
final byte[] multicastIpv4Addr = {(byte)224,0,0,1};
final byte[] multicastIpv6Addr = {(byte)0xff,2,0,0,0,0,0,0,0,0,0,0,0,0,0,(byte)0xfb};
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
LinkAddress link = new LinkAddress(InetAddress.getByAddress(unicastIpv4Addr), 24);
@@ -840,7 +844,7 @@ public class ApfTest extends AndroidTestCase {
lp.addLinkAddress(link);
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -903,7 +907,7 @@ public class ApfTest extends AndroidTestCase {
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
program = ipManagerCallback.getApfProgram();
assertDrop(program, mcastv4packet.array());
@@ -924,9 +928,10 @@ public class ApfTest extends AndroidTestCase {
LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
LinkProperties lp = new LinkProperties();
lp.addLinkAddress(link);
+ final int[] ethTypeBlackList = {};
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- ALLOW_802_3_FRAMES, mLog);
+ ALLOW_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
byte[] program = ipManagerCallback.getApfProgram();
@@ -948,7 +953,7 @@ public class ApfTest extends AndroidTestCase {
ipManagerCallback.resetApfProgramWait();
apfFilter.shutdown();
apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
apfFilter.setLinkProperties(lp);
program = ipManagerCallback.getApfProgram();
@@ -968,6 +973,70 @@ public class ApfTest extends AndroidTestCase {
apfFilter.shutdown();
}
+ @SmallTest
+ public void testApfFilterEthTypeBL() throws Exception {
+ MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
+ LinkProperties lp = new LinkProperties();
+ lp.addLinkAddress(link);
+ final int[] emptyBlackList = {};
+ final int[] ipv4BlackList = {ETH_P_IP};
+ final int[] ipv4Ipv6BlackList = {ETH_P_IP, ETH_P_IPV6};
+
+ ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, emptyBlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+
+ byte[] program = ipManagerCallback.getApfProgram();
+
+ // Verify empty packet of 100 zero bytes is passed
+ // Note that eth-type = 0 makes it an IEEE802.3 frame
+ ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+ assertPass(program, packet.array());
+
+ // Verify empty packet with IPv4 is passed
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertPass(program, packet.array());
+
+ // Verify empty IPv6 packet is passed
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertPass(program, packet.array());
+
+ // Now add IPv4 to the black list
+ ipManagerCallback.resetApfProgramWait();
+ apfFilter.shutdown();
+ apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, ipv4BlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+ program = ipManagerCallback.getApfProgram();
+
+ // Verify that IPv4 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertDrop(program, packet.array());
+
+ // Verify that IPv6 frame will pass
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertPass(program, packet.array());
+
+ // Now let us have both IPv4 and IPv6 in the black list
+ ipManagerCallback.resetApfProgramWait();
+ apfFilter.shutdown();
+ apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+ ALLOW_802_3_FRAMES, ipv4Ipv6BlackList, mLog);
+ apfFilter.setLinkProperties(lp);
+ program = ipManagerCallback.getApfProgram();
+
+ // Verify that IPv4 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+ assertDrop(program, packet.array());
+
+ // Verify that IPv6 frame will be dropped
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+ assertDrop(program, packet.array());
+
+ apfFilter.shutdown();
+ }
+
private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
cb.resetApfProgramWait();
filter.setLinkProperties(lp);
@@ -991,9 +1060,10 @@ public class ApfTest extends AndroidTestCase {
@SmallTest
public void testApfFilterArp() throws Exception {
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
// Verify initially ARP request filter is off, and GARP filter is on.
verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
@@ -1114,8 +1184,9 @@ public class ApfTest extends AndroidTestCase {
@SmallTest
public void testApfFilterRa() throws Exception {
MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+ final int[] ethTypeBlackList = {};
TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
byte[] program = ipManagerCallback.getApfProgram();
final int ROUTER_LIFETIME = 1000;
@@ -1256,9 +1327,10 @@ public class ApfTest extends AndroidTestCase {
public void testRaParsing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback cb = new MockIpManagerCallback();
TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
for (int i = 0; i < 1000; i++) {
byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
r.nextBytes(packet);
@@ -1275,9 +1347,10 @@ public class ApfTest extends AndroidTestCase {
public void testRaProcessing() throws Exception {
final int maxRandomPacketSize = 512;
final Random r = new Random();
+ final int[] ethTypeBlackList = {};
MockIpManagerCallback cb = new MockIpManagerCallback();
TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
- DROP_802_3_FRAMES, mLog);
+ DROP_802_3_FRAMES, ethTypeBlackList, mLog);
for (int i = 0; i < 1000; i++) {
byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
r.nextBytes(packet);
diff --git a/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
new file mode 100644
index 000000000000..f849689abb23
--- /dev/null
+++ b/tests/net/java/android/net/ip/IpReachabilityMonitorTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 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 android.net.ip;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+
+import android.net.util.SharedLog;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+/**
+ * Tests for IpReachabilityMonitor.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpReachabilityMonitorTest {
+
+ @Mock IpReachabilityMonitor.Callback mCallback;
+ @Mock IpReachabilityMonitor.Dependencies mDependencies;
+ @Mock SharedLog mLog;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ IpReachabilityMonitor makeMonitor() {
+ return new IpReachabilityMonitor("fake0", 1, mLog, mCallback, null, mDependencies);
+ }
+
+ @Test
+ public void testNothing() {
+ IpReachabilityMonitor monitor = makeMonitor();
+ }
+}
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
new file mode 100644
index 000000000000..3aab9426bc3f
--- /dev/null
+++ b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 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 android.net.netlink;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+import android.system.OsConstants;
+import libcore.util.HexEncoding;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConntrackMessageTest {
+ private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
+
+ // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
+ public static final String CT_V4UPDATE_TCP_HEX =
+ // struct nlmsghdr
+ "50000000" + // length = 80
+ "0001" + // type = (1 << 8) | 0
+ "0501" + // flags
+ "01000000" + // seqno = 1
+ "00000000" + // pid = 0
+ // struct nfgenmsg
+ "02" + // nfgen_family = AF_INET
+ "00" + // version = NFNETLINK_V0
+ "0000" + // res_id
+ // struct nlattr
+ "3400" + // nla_len = 52
+ "0180" + // nla_type = nested CTA_TUPLE_ORIG
+ // struct nlattr
+ "1400" + // nla_len = 20
+ "0180" + // nla_type = nested CTA_TUPLE_IP
+ "0800 0100 C0A82BD1" + // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
+ "0800 0200 17D30D1A" + // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
+ // struct nlattr
+ "1C00" + // nla_len = 28
+ "0280" + // nla_type = nested CTA_TUPLE_PROTO
+ "0500 0100 06 000000" + // nla_type=CTA_PROTO_NUM, proto=6
+ "0600 0200 AD2D 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
+ "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+ // struct nlattr
+ "0800" + // nla_len = 8
+ "0700" + // nla_type = CTA_TIMEOUT
+ "00069780"; // nla_value = 432000 (big endian)
+ public static final byte[] CT_V4UPDATE_TCP_BYTES =
+ HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+ // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
+ public static final String CT_V4UPDATE_UDP_HEX =
+ // struct nlmsghdr
+ "50000000" + // length = 80
+ "0001" + // type = (1 << 8) | 0
+ "0501" + // flags
+ "01000000" + // seqno = 1
+ "00000000" + // pid = 0
+ // struct nfgenmsg
+ "02" + // nfgen_family = AF_INET
+ "00" + // version = NFNETLINK_V0
+ "0000" + // res_id
+ // struct nlattr
+ "3400" + // nla_len = 52
+ "0180" + // nla_type = nested CTA_TUPLE_ORIG
+ // struct nlattr
+ "1400" + // nla_len = 20
+ "0180" + // nla_type = nested CTA_TUPLE_IP
+ "0800 0100 6460A792" + // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
+ "0800 0200 D83AC50A" + // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
+ // struct nlattr
+ "1C00" + // nla_len = 28
+ "0280" + // nla_type = nested CTA_TUPLE_PROTO
+ "0500 0100 11 000000" + // nla_type=CTA_PROTO_NUM, proto=17
+ "0600 0200 90CD 0000" + // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
+ "0600 0300 01BB 0000" + // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+ // struct nlattr
+ "0800" + // nla_len = 8
+ "0700" + // nla_type = CTA_TIMEOUT
+ "000000B4"; // nla_value = 180 (big endian)
+ public static final byte[] CT_V4UPDATE_UDP_BYTES =
+ HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+ @Test
+ public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
+ assumeTrue(USING_LE);
+
+ final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ OsConstants.IPPROTO_TCP,
+ (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
+ (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
+ 432000);
+ assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
+ }
+
+ @Test
+ public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
+ assumeTrue(USING_LE);
+
+ final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+ OsConstants.IPPROTO_UDP,
+ (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
+ (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
+ 180);
+ assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
+ }
+}
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index f77608f95b3e..9115378969ca 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
import android.os.HandlerThread;
import android.os.Handler;
@@ -38,6 +39,7 @@ import android.support.test.runner.AndroidJUnit4;
import android.os.Message;
import android.os.Messenger;
import com.android.internal.util.AsyncChannel;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,6 +58,8 @@ public class NsdManagerTest {
@Mock INsdManager mService;
MockServiceHandler mServiceHandler;
+ NsdManager mManager;
+
long mTimeoutMs = 100; // non-final so that tests can adjust the value.
@Before
@@ -64,11 +68,23 @@ public class NsdManagerTest {
mServiceHandler = spy(MockServiceHandler.create(mContext));
when(mService.getMessenger()).thenReturn(new Messenger(mServiceHandler));
+
+ mManager = makeManager();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ waitForIdleHandler(mServiceHandler, mTimeoutMs);
+ mServiceHandler.chan.disconnect();
+ mServiceHandler.stop();
+ if (mManager != null) {
+ mManager.disconnect();
+ }
}
@Test
public void testResolveService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type");
@@ -88,7 +104,7 @@ public class NsdManagerTest {
@Test
public void testParallelResolveService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply = new NsdServiceInfo("resolved_name", "resolved_type");
@@ -111,7 +127,7 @@ public class NsdManagerTest {
@Test
public void testRegisterService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo request1 = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo request2 = new NsdServiceInfo("another_name", "another_type");
@@ -170,7 +186,7 @@ public class NsdManagerTest {
@Test
public void testDiscoverService() {
- NsdManager manager = makeManager();
+ NsdManager manager = mManager;
NsdServiceInfo reply1 = new NsdServiceInfo("a_name", "a_type");
NsdServiceInfo reply2 = new NsdServiceInfo("another_name", "a_type");
@@ -248,7 +264,7 @@ public class NsdManagerTest {
@Test
public void testInvalidCalls() {
- NsdManager manager = new NsdManager(mContext, mService);
+ NsdManager manager = mManager;
NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class);
@@ -351,6 +367,10 @@ public class NsdManagerTest {
}
}
+ public void stop() {
+ getLooper().quitSafely();
+ }
+
public static MockServiceHandler create(Context context) {
HandlerThread t = new HandlerThread("mock-service-handler");
t.start();
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index f6481cf59140..8816d43ef8de 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -64,6 +64,7 @@ import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
+import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.StringNetworkSpecifier;
import android.net.metrics.IpConnectivityLog;
@@ -88,6 +89,7 @@ import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.LogPrinter;
@@ -109,7 +111,10 @@ import org.mockito.Spy;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -304,6 +309,10 @@ public class ConnectivityServiceTest extends AndroidTestCase {
private String mRedirectUrl;
MockNetworkAgent(int transport) {
+ this(transport, new LinkProperties());
+ }
+
+ MockNetworkAgent(int transport, LinkProperties linkProperties) {
final int type = transportToLegacyType(transport);
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
@@ -329,7 +338,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
mHandlerThread.start();
mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
"Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
- new LinkProperties(), mScore, new NetworkMisc()) {
+ linkProperties, mScore, new NetworkMisc()) {
@Override
public void unwanted() { mDisconnected.open(); }
@@ -3338,6 +3347,68 @@ public class ConnectivityServiceTest extends AndroidTestCase {
assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
}
+ @SmallTest
+ public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
+ final NetworkRequest networkRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+ mCm.registerNetworkCallback(networkRequest, networkCallback);
+
+ LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName("wlan0");
+ LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
+ RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
+ NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+ lp.addLinkAddress(myIpv4Address);
+ lp.addRoute(myIpv4DefaultRoute);
+
+ // Verify direct routes are added when network agent is first registered in
+ // ConnectivityService.
+ MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
+ networkAgent.connect(true);
+ networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
+ networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
+ CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ networkAgent);
+ networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
+ networkCallback.assertNoCallback();
+ checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
+ Arrays.asList(myIpv4DefaultRoute));
+ checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
+ Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
+
+ // Verify direct routes are added during subsequent link properties updates.
+ LinkProperties newLp = new LinkProperties(lp);
+ LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
+ LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
+ newLp.addLinkAddress(myIpv6Address1);
+ newLp.addLinkAddress(myIpv6Address2);
+ networkAgent.sendLinkProperties(newLp);
+ cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
+ networkCallback.assertNoCallback();
+ checkDirectlyConnectedRoutes(cbi.arg,
+ Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
+ Arrays.asList(myIpv4DefaultRoute));
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
+
+ private void checkDirectlyConnectedRoutes(Object callbackObj,
+ Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
+ assertTrue(callbackObj instanceof LinkProperties);
+ LinkProperties lp = (LinkProperties) callbackObj;
+
+ Set<RouteInfo> expectedRoutes = new ArraySet<>();
+ expectedRoutes.addAll(otherRoutes);
+ for (LinkAddress address : linkAddresses) {
+ RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
+ // Duplicates in linkAddresses are considered failures
+ assertTrue(expectedRoutes.add(localRoute));
+ }
+ List<RouteInfo> observedRoutes = lp.getRoutes();
+ assertEquals(expectedRoutes.size(), observedRoutes.size());
+ assertTrue(observedRoutes.containsAll(expectedRoutes));
+ }
+
private static <T> void assertEmpty(T[] ts) {
int length = ts.length;
assertEquals("expected empty array, but length was " + length, 0, length);
diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java
new file mode 100644
index 000000000000..23fee286b8e7
--- /dev/null
+++ b/tests/net/java/com/android/server/IpSecServiceTest.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.EADDRINUSE;
+import static android.system.OsConstants.IPPROTO_UDP;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.INetd;
+import android.net.IpSecAlgorithm;
+import android.net.IpSecConfig;
+import android.net.IpSecManager;
+import android.net.IpSecSpiResponse;
+import android.net.IpSecTransform;
+import android.net.IpSecTransformResponse;
+import android.net.IpSecUdpEncapResponse;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.support.test.filters.SmallTest;
+import android.system.ErrnoException;
+import android.system.Os;
+import java.io.FileDescriptor;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link IpSecService}. */
+@SmallTest
+@RunWith(JUnit4.class)
+public class IpSecServiceTest {
+
+ private static final int DROID_SPI = 0xD1201D;
+ private static final int DROID_SPI2 = DROID_SPI + 1;
+ private static final int TEST_UDP_ENCAP_INVALID_PORT = 100;
+ private static final int TEST_UDP_ENCAP_PORT_OUT_RANGE = 100000;
+ private static final int TEST_UDP_ENCAP_PORT = 34567;
+
+ private static final String IPV4_LOOPBACK = "127.0.0.1";
+ private static final String IPV4_ADDR = "192.168.0.2";
+
+ private static final InetAddress INADDR_ANY;
+
+ static {
+ try {
+ INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0});
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static final int[] DIRECTIONS =
+ new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN};
+ private static final byte[] CRYPT_KEY = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
+ };
+ private static final byte[] AUTH_KEY = {
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F
+ };
+
+ Context mMockContext;
+ INetd mMockNetd;
+ IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig;
+ IpSecService mIpSecService;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockContext = mock(Context.class);
+ mMockNetd = mock(INetd.class);
+ mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class);
+ mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig);
+
+ // Injecting mock netd
+ when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd);
+ }
+
+ @Test
+ public void testIpSecServiceCreate() throws InterruptedException {
+ IpSecService ipSecSrv = IpSecService.create(mMockContext);
+ assertNotNull(ipSecSrv);
+ }
+
+ @Test
+ public void testIpSecServiceReserveSpi() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(IPV4_LOOPBACK),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
+ assertEquals(IpSecManager.Status.OK, spiResp.status);
+ assertEquals(DROID_SPI, spiResp.spi);
+ }
+
+ @Test
+ public void testReleaseSecurityParameterIndex() throws Exception {
+ when(mMockNetd.ipSecAllocateSpi(
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ eq(IPV4_LOOPBACK),
+ eq(DROID_SPI)))
+ .thenReturn(DROID_SPI);
+
+ IpSecSpiResponse spiResp =
+ mIpSecService.reserveSecurityParameterIndex(
+ IpSecTransform.DIRECTION_OUT, IPV4_LOOPBACK, DROID_SPI, new Binder());
+
+ mIpSecService.releaseSecurityParameterIndex(spiResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(spiResp.resourceId), anyInt(), anyString(), anyString(), eq(DROID_SPI));
+ }
+
+ @Test
+ public void testReleaseInvalidSecurityParameterIndex() throws Exception {
+ try {
+ mIpSecService.releaseSecurityParameterIndex(1);
+ fail("IllegalArgumentException not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /** This function finds an available port */
+ int findUnusedPort() throws Exception {
+ // Get an available port.
+ ServerSocket s = new ServerSocket(0);
+ int port = s.getLocalPort();
+ s.close();
+ return port;
+ }
+
+ @Test
+ public void testOpenAndCloseUdpEncapsulationSocket() throws Exception {
+ int localport = findUnusedPort();
+
+ IpSecUdpEncapResponse udpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertNotNull(udpEncapResp);
+ assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
+ assertEquals(localport, udpEncapResp.port);
+
+ mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
+ udpEncapResp.fileDescriptor.close();
+
+ // TODO: Added check for the resource tracker
+ }
+
+ @Test
+ public void testOpenUdpEncapsulationSocketAfterClose() throws Exception {
+ int localport = findUnusedPort();
+ IpSecUdpEncapResponse udpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertNotNull(udpEncapResp);
+ assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
+ assertEquals(localport, udpEncapResp.port);
+
+ mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
+ udpEncapResp.fileDescriptor.close();
+
+ /** Check if localport is available. */
+ FileDescriptor newSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ Os.bind(newSocket, INADDR_ANY, localport);
+ Os.close(newSocket);
+ }
+
+ /**
+ * This function checks if the IpSecService holds the reserved port. If
+ * closeUdpEncapsulationSocket is not called, the socket cleanup should not be complete.
+ */
+ @Test
+ public void testUdpEncapPortNotReleased() throws Exception {
+ int localport = findUnusedPort();
+ IpSecUdpEncapResponse udpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertNotNull(udpEncapResp);
+ assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
+ assertEquals(localport, udpEncapResp.port);
+
+ udpEncapResp.fileDescriptor.close();
+
+ FileDescriptor newSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ try {
+ Os.bind(newSocket, INADDR_ANY, localport);
+ fail("ErrnoException not thrown");
+ } catch (ErrnoException e) {
+ assertEquals(EADDRINUSE, e.errno);
+ }
+ mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
+ }
+
+ @Test
+ public void testOpenUdpEncapsulationSocketOnRandomPort() throws Exception {
+ IpSecUdpEncapResponse udpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(0, new Binder());
+ assertNotNull(udpEncapResp);
+ assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
+ mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
+ udpEncapResp.fileDescriptor.close();
+ }
+
+ @Test
+ public void testOpenUdpEncapsulationSocketPortRange() throws Exception {
+ try {
+ mIpSecService.openUdpEncapsulationSocket(TEST_UDP_ENCAP_INVALID_PORT, new Binder());
+ fail("IllegalArgumentException not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+
+ try {
+ mIpSecService.openUdpEncapsulationSocket(TEST_UDP_ENCAP_PORT_OUT_RANGE, new Binder());
+ fail("IllegalArgumentException not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testOpenUdpEncapsulationSocketTwice() throws Exception {
+ int localport = findUnusedPort();
+
+ IpSecUdpEncapResponse udpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertNotNull(udpEncapResp);
+ assertEquals(IpSecManager.Status.OK, udpEncapResp.status);
+ assertEquals(localport, udpEncapResp.port);
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+
+ IpSecUdpEncapResponse testUdpEncapResp =
+ mIpSecService.openUdpEncapsulationSocket(localport, new Binder());
+ assertEquals(IpSecManager.Status.RESOURCE_UNAVAILABLE, testUdpEncapResp.status);
+
+ mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId);
+ udpEncapResp.fileDescriptor.close();
+ }
+
+ @Test
+ public void testCloseInvalidUdpEncapsulationSocket() throws Exception {
+ try {
+ mIpSecService.closeUdpEncapsulationSocket(1);
+ fail("IllegalArgumentException not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ IpSecConfig buildIpSecConfig() throws Exception {
+ IpSecManager ipSecManager = new IpSecManager(mIpSecService);
+
+ // Mocking the netd to allocate SPI
+ when(mMockNetd.ipSecAllocateSpi(anyInt(), anyInt(), anyString(), anyString(), anyInt()))
+ .thenReturn(DROID_SPI)
+ .thenReturn(DROID_SPI2);
+
+ IpSecAlgorithm encryptAlgo = new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY);
+ IpSecAlgorithm authAlgo =
+ new IpSecAlgorithm(IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 8);
+
+ InetAddress localAddr = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
+
+ /** Allocate and add SPI records in the IpSecService through IpSecManager interface. */
+ IpSecManager.SecurityParameterIndex outSpi =
+ ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, localAddr);
+ IpSecManager.SecurityParameterIndex inSpi =
+ ipSecManager.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, localAddr);
+
+ IpSecConfig ipSecConfig =
+ new IpSecTransform.Builder(mMockContext)
+ .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
+ .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
+ .setEncryption(IpSecTransform.DIRECTION_OUT, encryptAlgo)
+ .setAuthentication(IpSecTransform.DIRECTION_OUT, authAlgo)
+ .setEncryption(IpSecTransform.DIRECTION_IN, encryptAlgo)
+ .setAuthentication(IpSecTransform.DIRECTION_IN, authAlgo)
+ .getIpSecConfig();
+ return ipSecConfig;
+ }
+
+ @Test
+ public void testCreateTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ verify(mMockNetd)
+ .ipSecAddSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ anyInt(),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ anyLong(),
+ eq(DROID_SPI2),
+ eq(IpSecAlgorithm.AUTH_HMAC_SHA256),
+ eq(AUTH_KEY),
+ anyInt(),
+ eq(IpSecAlgorithm.CRYPT_AES_CBC),
+ eq(CRYPT_KEY),
+ anyInt(),
+ anyInt(),
+ anyInt(),
+ anyInt());
+ }
+
+ @Test
+ public void testDeleteTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ mIpSecService.deleteTransportModeTransform(createTransformResp.resourceId);
+
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecDeleteSecurityAssociation(
+ eq(createTransformResp.resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testDeleteInvalidTransportModeTransform() throws Exception {
+ try {
+ mIpSecService.deleteTransportModeTransform(1);
+ fail("IllegalArgumentException not thrown");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testApplyTransportModeTransform() throws Exception {
+ IpSecConfig ipSecConfig = buildIpSecConfig();
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransportModeTransform(ipSecConfig, new Binder());
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+
+ int resourceId = createTransformResp.resourceId;
+ mIpSecService.applyTransportModeTransform(pfd, resourceId);
+
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_OUT),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI));
+ verify(mMockNetd)
+ .ipSecApplyTransportModeTransform(
+ eq(pfd.getFileDescriptor()),
+ eq(resourceId),
+ eq(IpSecTransform.DIRECTION_IN),
+ anyString(),
+ anyString(),
+ eq(DROID_SPI2));
+ }
+
+ @Test
+ public void testRemoveTransportModeTransform() throws Exception {
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket());
+ mIpSecService.removeTransportModeTransform(pfd, 1);
+
+ verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd.getFileDescriptor());
+ }
+}
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
new file mode 100644
index 000000000000..2ac73dbd4f52
--- /dev/null
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2012 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.content.Context;
+import android.net.INetd;
+import android.net.LinkAddress;
+import android.net.LocalSocket;
+import android.net.LocalServerSocket;
+import android.os.BatteryStats;
+import android.os.Binder;
+import android.os.IBinder;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.server.NetworkManagementService.SystemServices;
+import com.android.server.net.BaseNetworkObserver;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link NetworkManagementService}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkManagementServiceTest {
+
+ private static final String SOCKET_NAME = "__test__NetworkManagementServiceTest";
+ private NetworkManagementService mNMService;
+ private LocalServerSocket mServerSocket;
+ private LocalSocket mSocket;
+ private OutputStream mOutputStream;
+
+ @Mock private Context mContext;
+ @Mock private IBatteryStats.Stub mBatteryStatsService;
+ @Mock private INetd.Stub mNetdService;
+
+ private final SystemServices mServices = new SystemServices() {
+ @Override
+ public IBinder getService(String name) {
+ switch (name) {
+ case BatteryStats.SERVICE_NAME:
+ return mBatteryStatsService;
+ default:
+ throw new UnsupportedOperationException("Unknown service " + name);
+ }
+ }
+ @Override
+ public void registerLocalService(NetworkManagementInternal nmi) {
+ }
+ @Override
+ public INetd getNetd() {
+ return mNetdService;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ // Set up a sheltered test environment.
+ mServerSocket = new LocalServerSocket(SOCKET_NAME);
+
+ // Start the service and wait until it connects to our socket.
+ mNMService = NetworkManagementService.create(mContext, SOCKET_NAME, mServices);
+ mSocket = mServerSocket.accept();
+ mOutputStream = mSocket.getOutputStream();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mSocket != null) mSocket.close();
+ if (mServerSocket != null) mServerSocket.close();
+ }
+
+ /**
+ * Sends a message on the netd socket and gives the events some time to make it back.
+ */
+ private void sendMessage(String message) throws IOException {
+ // Strings are null-terminated, so add "\0" at the end.
+ mOutputStream.write((message + "\0").getBytes());
+ }
+
+ private static <T> T expectSoon(T mock) {
+ return verify(mock, timeout(200));
+ }
+
+ /**
+ * Tests that network observers work properly.
+ */
+ @Test
+ public void testNetworkObservers() throws Exception {
+ BaseNetworkObserver observer = mock(BaseNetworkObserver.class);
+ doReturn(new Binder()).when(observer).asBinder(); // Used by registerObserver.
+ mNMService.registerObserver(observer);
+
+ // Forget everything that happened to the mock so far, so we can explicitly verify
+ // everything that happens and does not happen to it from now on.
+ reset(observer);
+
+ // Now send NetworkManagementService messages and ensure that the observer methods are
+ // called. After every valid message we expect a callback soon after; to ensure that
+ // invalid messages don't cause any callbacks, we call verifyNoMoreInteractions at the end.
+
+ /**
+ * Interface changes.
+ */
+ sendMessage("600 Iface added rmnet12");
+ expectSoon(observer).interfaceAdded("rmnet12");
+
+ sendMessage("600 Iface removed eth1");
+ expectSoon(observer).interfaceRemoved("eth1");
+
+ sendMessage("607 Iface removed eth1");
+ // Invalid code.
+
+ sendMessage("600 Iface borked lo down");
+ // Invalid event.
+
+ sendMessage("600 Iface changed clat4 up again");
+ // Extra tokens.
+
+ sendMessage("600 Iface changed clat4 up");
+ expectSoon(observer).interfaceStatusChanged("clat4", true);
+
+ sendMessage("600 Iface linkstate rmnet0 down");
+ expectSoon(observer).interfaceLinkStateChanged("rmnet0", false);
+
+ sendMessage("600 IFACE linkstate clat4 up");
+ // Invalid group.
+
+ /**
+ * Bandwidth control events.
+ */
+ sendMessage("601 limit alert data rmnet_usb0");
+ expectSoon(observer).limitReached("data", "rmnet_usb0");
+
+ sendMessage("601 invalid alert data rmnet0");
+ // Invalid group.
+
+ sendMessage("601 limit increased data rmnet0");
+ // Invalid event.
+
+
+ /**
+ * Interface class activity.
+ */
+
+ sendMessage("613 IfaceClass active 1 1234 10012");
+ expectSoon(observer).interfaceClassDataActivityChanged("1", true, 1234);
+
+ sendMessage("613 IfaceClass idle 9 5678");
+ expectSoon(observer).interfaceClassDataActivityChanged("9", false, 5678);
+
+ sendMessage("613 IfaceClass reallyactive 9 4321");
+ expectSoon(observer).interfaceClassDataActivityChanged("9", false, 4321);
+
+ sendMessage("613 InterfaceClass reallyactive 1");
+ // Invalid group.
+
+
+ /**
+ * IP address changes.
+ */
+ sendMessage("614 Address updated fe80::1/64 wlan0 128 253");
+ expectSoon(observer).addressUpdated("wlan0", new LinkAddress("fe80::1/64", 128, 253));
+
+ // There is no "added", so we take this as "removed".
+ sendMessage("614 Address added fe80::1/64 wlan0 128 253");
+ expectSoon(observer).addressRemoved("wlan0", new LinkAddress("fe80::1/64", 128, 253));
+
+ sendMessage("614 Address removed 2001:db8::1/64 wlan0 1 0");
+ expectSoon(observer).addressRemoved("wlan0", new LinkAddress("2001:db8::1/64", 1, 0));
+
+ sendMessage("614 Address removed 2001:db8::1/64 wlan0 1");
+ // Not enough arguments.
+
+ sendMessage("666 Address removed 2001:db8::1/64 wlan0 1 0");
+ // Invalid code.
+
+
+ /**
+ * DNS information broadcasts.
+ */
+ sendMessage("615 DnsInfo servers rmnet_usb0 3600 2001:db8::1");
+ expectSoon(observer).interfaceDnsServerInfo("rmnet_usb0", 3600,
+ new String[]{"2001:db8::1"});
+
+ sendMessage("615 DnsInfo servers wlan0 14400 2001:db8::1,2001:db8::2");
+ expectSoon(observer).interfaceDnsServerInfo("wlan0", 14400,
+ new String[]{"2001:db8::1", "2001:db8::2"});
+
+ // We don't check for negative lifetimes, only for parse errors.
+ sendMessage("615 DnsInfo servers wlan0 -3600 ::1");
+ expectSoon(observer).interfaceDnsServerInfo("wlan0", -3600,
+ new String[]{"::1"});
+
+ sendMessage("615 DnsInfo servers wlan0 SIXHUNDRED ::1");
+ // Non-numeric lifetime.
+
+ sendMessage("615 DnsInfo servers wlan0 2001:db8::1");
+ // Missing lifetime.
+
+ sendMessage("615 DnsInfo servers wlan0 3600");
+ // No servers.
+
+ sendMessage("615 DnsInfo servers 3600 wlan0 2001:db8::1,2001:db8::2");
+ // Non-numeric lifetime.
+
+ sendMessage("615 DnsInfo wlan0 7200 2001:db8::1,2001:db8::2");
+ // Invalid tokens.
+
+ sendMessage("666 DnsInfo servers wlan0 5400 2001:db8::1");
+ // Invalid code.
+
+ // No syntax checking on the addresses.
+ sendMessage("615 DnsInfo servers wlan0 600 ,::,,foo,::1,");
+ expectSoon(observer).interfaceDnsServerInfo("wlan0", 600,
+ new String[]{"", "::", "", "foo", "::1"});
+
+ // Make sure nothing else was called.
+ verifyNoMoreInteractions(observer);
+ }
+}
diff --git a/tests/net/java/com/android/server/NsdServiceTest.java b/tests/net/java/com/android/server/NsdServiceTest.java
index 68cb251cf87e..2e49c98ca9b6 100644
--- a/tests/net/java/com/android/server/NsdServiceTest.java
+++ b/tests/net/java/com/android/server/NsdServiceTest.java
@@ -95,6 +95,9 @@ public class NsdServiceTest {
client2.disconnect();
verify(mDaemon, timeout(mTimeoutMs).times(1)).stop();
+
+ client1.disconnect();
+ client2.disconnect();
}
@Test
@@ -131,6 +134,8 @@ public class NsdServiceTest {
// checks that request are cleaned
verifyDaemonCommands("stop-register 2", "stop-discover 3", "stop-resolve 4");
+
+ client.disconnect();
}
NsdService makeService() {
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
new file mode 100644
index 000000000000..e3f46a40e2b1
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2017 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.connectivity;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.os.Handler;
+import android.os.INetworkManagementService;
+import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.ConnectivityService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class Nat464XlatTest {
+
+ static final String BASE_IFACE = "test0";
+ static final String STACKED_IFACE = "v4-test0";
+ static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
+
+ @Mock ConnectivityService mConnectivity;
+ @Mock INetworkManagementService mNms;
+ @Mock InterfaceConfiguration mConfig;
+ @Mock NetworkAgentInfo mNai;
+
+ TestLooper mLooper;
+ Handler mHandler;
+
+ Nat464Xlat makeNat464Xlat() {
+ return new Nat464Xlat(mNms, mNai);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ MockitoAnnotations.initMocks(this);
+
+ mNai.linkProperties = new LinkProperties();
+ mNai.linkProperties.setInterfaceName(BASE_IFACE);
+ mNai.networkInfo = new NetworkInfo(null);
+ mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
+ when(mNai.connService()).thenReturn(mConnectivity);
+ when(mNai.handler()).thenReturn(mHandler);
+
+ when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
+ when(mConfig.getLinkAddress()).thenReturn(ADDR);
+ }
+
+ @Test
+ public void testNormalStartAndStop() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+ ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // Stacked interface up notification arrives.
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+ verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
+ verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertFalse(c.getValue().getStackedLinks().isEmpty());
+ assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertRunning(nat);
+
+ // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
+ nat.stop();
+
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
+
+ // Stacked interface removed notification arrives.
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertTrue(c.getValue().getStackedLinks().isEmpty());
+ assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testClatdCrashWhileRunning() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+ ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // Stacked interface up notification arrives.
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+ verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
+ verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertFalse(c.getValue().getStackedLinks().isEmpty());
+ assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertRunning(nat);
+
+ // Stacked interface removed notification arrives (clatd crashed, ...).
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
+ verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
+ assertTrue(c.getValue().getStackedLinks().isEmpty());
+ assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
+ assertIdle(nat);
+
+ // ConnectivityService stops clat: no-op.
+ nat.stop();
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testStopBeforeClatdStarts() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
+ nat.stop();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ assertIdle(nat);
+
+ // In-flight interface up notification arrives: no-op
+ nat.interfaceLinkStateChanged(STACKED_IFACE, true);
+ mLooper.dispatchNext();
+
+
+ // Interface removed notification arrives after stopClatd() takes effect: no-op.
+ nat.interfaceRemoved(STACKED_IFACE);
+ mLooper.dispatchNext();
+
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ @Test
+ public void testStopAndClatdNeverStarts() throws Exception {
+ Nat464Xlat nat = makeNat464Xlat();
+
+ // ConnectivityService starts clat.
+ nat.start();
+
+ verify(mNms).registerObserver(eq(nat));
+ verify(mNms).startClatd(eq(BASE_IFACE));
+
+ // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
+ nat.stop();
+
+ verify(mNms).unregisterObserver(eq(nat));
+ verify(mNms).stopClatd(eq(BASE_IFACE));
+ assertIdle(nat);
+
+ verifyNoMoreInteractions(mNms, mConnectivity);
+ }
+
+ static void assertIdle(Nat464Xlat nat) {
+ assertTrue("Nat464Xlat was not IDLE", !nat.isStarted());
+ }
+
+ static void assertRunning(Nat464Xlat nat) {
+ assertTrue("Nat464Xlat was not RUNNING", nat.isRunning());
+ }
+}
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index dfe3f982e5bf..7a2ff8995458 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -32,12 +32,13 @@ import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -436,6 +437,9 @@ public class OffloadControllerTest {
ethernetStats.txBytes = 100000;
when(mHardware.getForwardedStats(eq(ethernetIface))).thenReturn(ethernetStats);
offload.setUpstreamLinkProperties(null);
+ // Expect that we first clear the HAL's upstream parameters.
+ inOrder.verify(mHardware, times(1)).setUpstreamParameters(
+ eq(""), eq("0.0.0.0"), eq("0.0.0.0"), eq(null));
// Expect that we fetch stats from the previous upstream.
inOrder.verify(mHardware, times(1)).getForwardedStats(eq(ethernetIface));
@@ -445,8 +449,6 @@ public class OffloadControllerTest {
waitForIdle();
// There is no current upstream, so no stats are fetched.
inOrder.verify(mHardware, never()).getForwardedStats(any());
- inOrder.verify(mHardware, times(1)).setUpstreamParameters(
- eq(null), eq(null), eq(null), eq(null));
inOrder.verifyNoMoreInteractions();
assertEquals(2, stats.size());
@@ -621,6 +623,73 @@ public class OffloadControllerTest {
inOrder.verifyNoMoreInteractions();
}
+ @Test
+ public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception {
+ setupFunctioningHardwareInterface();
+ enableOffload();
+
+ final OffloadController offload = makeOffloadController();
+ offload.start();
+
+ // Pretend to set a few different upstreams (only the interface name
+ // matters for this test; we're ignoring IP and route information).
+ final LinkProperties upstreamLp = new LinkProperties();
+ for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
+ upstreamLp.setInterfaceName(ifname);
+ offload.setUpstreamLinkProperties(upstreamLp);
+ }
+
+ // Clear invocation history, especially the getForwardedStats() calls
+ // that happen with setUpstreamParameters().
+ clearInvocations(mHardware);
+
+ OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ callback.onStoppedUnsupported();
+
+ // Verify forwarded stats behaviour.
+ verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
+ verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
+ verifyNoMoreInteractions(mHardware);
+ verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
+ verifyNoMoreInteractions(mNMService);
+ }
+
+ @Test
+ public void testControlCallbackOnSupportAvailableFetchesAllStatsAndPushesAllParameters()
+ throws Exception {
+ setupFunctioningHardwareInterface();
+ enableOffload();
+
+ final OffloadController offload = makeOffloadController();
+ offload.start();
+
+ // Pretend to set a few different upstreams (only the interface name
+ // matters for this test; we're ignoring IP and route information).
+ final LinkProperties upstreamLp = new LinkProperties();
+ for (String ifname : new String[]{RMNET0, WLAN0, RMNET0}) {
+ upstreamLp.setInterfaceName(ifname);
+ offload.setUpstreamLinkProperties(upstreamLp);
+ }
+
+ // Clear invocation history, especially the getForwardedStats() calls
+ // that happen with setUpstreamParameters().
+ clearInvocations(mHardware);
+
+ OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
+ callback.onSupportAvailable();
+
+ // Verify forwarded stats behaviour.
+ verify(mHardware, times(1)).getForwardedStats(eq(RMNET0));
+ verify(mHardware, times(1)).getForwardedStats(eq(WLAN0));
+ verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
+ verifyNoMoreInteractions(mNMService);
+
+ // TODO: verify local prefixes and downstreams are also pushed to the HAL.
+ verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
+ verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
+ verifyNoMoreInteractions(mHardware);
+ }
+
private static void assertArrayListContains(ArrayList<String> list, String... elems) {
for (String element : elems) {
assertTrue(list.contains(element));
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 2a32b73d56da..9c1026465612 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -17,26 +17,39 @@
package com.android.server.net;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.os.Process.myUid;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.server.net.NetworkStatsCollection.multiplySafe;
+
import android.content.res.Resources;
+import android.net.ConnectivityManager;
import android.net.NetworkIdentity;
import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.Process;
import android.os.UserHandle;
+import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
-import android.support.test.filters.SmallTest;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.format.DateUtils;
+import android.util.RecurrenceRule;
import com.android.frameworks.tests.net.R;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
@@ -44,9 +57,12 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.List;
/**
* Tests for {@link NetworkStatsCollection}.
@@ -57,14 +73,31 @@ public class NetworkStatsCollectionTest extends AndroidTestCase {
private static final String TEST_FILE = "test.bin";
private static final String TEST_IMSI = "310260000000000";
+ private static final long TIME_A = 1326088800000L; // UTC: Monday 9th January 2012 06:00:00 AM
+ private static final long TIME_B = 1326110400000L; // UTC: Monday 9th January 2012 12:00:00 PM
+ private static final long TIME_C = 1326132000000L; // UTC: Monday 9th January 2012 06:00:00 PM
+
+ private static Clock sOriginalClock;
+
@Override
public void setUp() throws Exception {
super.setUp();
+ sOriginalClock = RecurrenceRule.sClock;
// ignore any device overlay while testing
NetworkTemplate.forceAllNetworkTypes();
}
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ RecurrenceRule.sClock = sOriginalClock;
+ }
+
+ private void setClock(Instant instant) {
+ RecurrenceRule.sClock = Clock.fixed(instant, ZoneId.systemDefault());
+ }
+
public void testReadLegacyNetwork() throws Exception {
final File testFile = new File(getContext().getFilesDir(), TEST_FILE);
stageFile(R.raw.netstats_v1, testFile);
@@ -198,11 +231,11 @@ public class NetworkStatsCollectionTest extends AndroidTestCase {
collection.getRelevantUids(NetworkStatsAccess.Level.DEVICE));
// Verify security check in getHistory.
- assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), myUid, SET_DEFAULT,
- TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT));
+ assertNotNull(collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, myUid, SET_DEFAULT,
+ TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid));
try {
- collection.getHistory(buildTemplateMobileAll(TEST_IMSI), otherUidInSameUser,
- SET_DEFAULT, TAG_NONE, 0, NetworkStatsAccess.Level.DEFAULT);
+ collection.getHistory(buildTemplateMobileAll(TEST_IMSI), null, otherUidInSameUser,
+ SET_DEFAULT, TAG_NONE, 0, 0L, 0L, NetworkStatsAccess.Level.DEFAULT, myUid);
fail("Should have thrown SecurityException for accessing different UID");
} catch (SecurityException e) {
// expected
@@ -217,6 +250,257 @@ public class NetworkStatsCollectionTest extends AndroidTestCase {
0, NetworkStatsAccess.Level.DEVICE);
}
+ public void testAugmentPlan() throws Exception {
+ final File testFile = new File(getContext().getFilesDir(), TEST_FILE);
+ stageFile(R.raw.netstats_v1, testFile);
+
+ final NetworkStatsCollection emptyCollection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
+ final NetworkStatsCollection collection = new NetworkStatsCollection(30 * MINUTE_IN_MILLIS);
+ collection.readLegacyNetwork(testFile);
+
+ // We're in the future, but not that far off
+ setClock(Instant.parse("2012-06-01T00:00:00.00Z"));
+
+ // Test a bunch of plans that should result in no augmentation
+ final List<SubscriptionPlan> plans = new ArrayList<>();
+
+ // No plan
+ plans.add(null);
+ // No usage anchor
+ plans.add(SubscriptionPlan.Builder
+ .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z")).build());
+ // Usage anchor far in past
+ plans.add(SubscriptionPlan.Builder
+ .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z"))
+ .setDataUsage(1000L, TIME_A - DateUtils.YEAR_IN_MILLIS).build());
+ // Usage anchor far in future
+ plans.add(SubscriptionPlan.Builder
+ .createRecurringMonthly(ZonedDateTime.parse("2011-01-14T00:00:00.00Z"))
+ .setDataUsage(1000L, TIME_A + DateUtils.YEAR_IN_MILLIS).build());
+ // Usage anchor near but outside cycle
+ plans.add(SubscriptionPlan.Builder
+ .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"),
+ ZonedDateTime.parse("2012-01-09T15:00:00.00Z"))
+ .setDataUsage(1000L, TIME_C).build());
+
+ for (SubscriptionPlan plan : plans) {
+ int i;
+ NetworkStatsHistory history;
+
+ // Empty collection should be untouched
+ history = getHistory(emptyCollection, plan, TIME_A, TIME_C);
+ assertEquals(0L, history.getTotalBytes());
+
+ // Normal collection should be untouched
+ history = getHistory(collection, plan, TIME_A, TIME_C); i = 0;
+ assertEntry(100647, 197, 23649, 185, history.getValues(i++, null));
+ assertEntry(100647, 196, 23648, 185, history.getValues(i++, null));
+ assertEntry(18323, 76, 15032, 76, history.getValues(i++, null));
+ assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
+ assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
+ assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
+ assertEntry(10747, 50, 16838, 55, history.getValues(i++, null));
+ assertEntry(10747, 49, 16838, 54, history.getValues(i++, null));
+ assertEntry(89191, 151, 18021, 140, history.getValues(i++, null));
+ assertEntry(89190, 150, 18020, 139, history.getValues(i++, null));
+ assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
+ assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
+ assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
+ assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
+ assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEquals(history.size(), i);
+
+ // Slice from middle should be untouched
+ history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
+ TIME_B + HOUR_IN_MILLIS); i = 0;
+ assertEntry(3821, 22, 4525, 26, history.getValues(i++, null));
+ assertEntry(3820, 22, 4524, 26, history.getValues(i++, null));
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEquals(history.size(), i);
+ }
+
+ // Lower anchor in the middle of plan
+ {
+ int i;
+ NetworkStatsHistory history;
+
+ final SubscriptionPlan plan = SubscriptionPlan.Builder
+ .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"),
+ ZonedDateTime.parse("2012-01-09T15:00:00.00Z"))
+ .setDataUsage(200000L, TIME_B).build();
+
+ // Empty collection should be augmented
+ history = getHistory(emptyCollection, plan, TIME_A, TIME_C);
+ assertEquals(200000L, history.getTotalBytes());
+
+ // Normal collection should be augmented
+ history = getHistory(collection, plan, TIME_A, TIME_C); i = 0;
+ assertEntry(100647, 197, 23649, 185, history.getValues(i++, null));
+ assertEntry(100647, 196, 23648, 185, history.getValues(i++, null));
+ assertEntry(18323, 76, 15032, 76, history.getValues(i++, null));
+ assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
+ assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
+ assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
+ // Cycle point; start data normalization
+ assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
+ assertEntry(7507, 0, 11763, 0, history.getValues(i++, null));
+ assertEntry(62309, 0, 12589, 0, history.getValues(i++, null));
+ assertEntry(62309, 0, 12588, 0, history.getValues(i++, null));
+ assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
+ assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
+ // Anchor point; end data normalization
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
+ assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
+ // Cycle point
+ assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
+ assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
+ assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+ assertEquals(history.size(), i);
+
+ // Slice from middle should be augmented
+ history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
+ TIME_B + HOUR_IN_MILLIS); i = 0;
+ assertEntry(2669, 0, 3161, 0, history.getValues(i++, null));
+ assertEntry(2668, 0, 3160, 0, history.getValues(i++, null));
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEquals(history.size(), i);
+ }
+
+ // Higher anchor in the middle of plan
+ {
+ int i;
+ NetworkStatsHistory history;
+
+ final SubscriptionPlan plan = SubscriptionPlan.Builder
+ .createNonrecurring(ZonedDateTime.parse("2012-01-09T09:00:00.00Z"),
+ ZonedDateTime.parse("2012-01-09T15:00:00.00Z"))
+ .setDataUsage(400000L, TIME_B + MINUTE_IN_MILLIS).build();
+
+ // Empty collection should be augmented
+ history = getHistory(emptyCollection, plan, TIME_A, TIME_C);
+ assertEquals(400000L, history.getTotalBytes());
+
+ // Normal collection should be augmented
+ history = getHistory(collection, plan, TIME_A, TIME_C); i = 0;
+ assertEntry(100647, 197, 23649, 185, history.getValues(i++, null));
+ assertEntry(100647, 196, 23648, 185, history.getValues(i++, null));
+ assertEntry(18323, 76, 15032, 76, history.getValues(i++, null));
+ assertEntry(18322, 75, 15031, 75, history.getValues(i++, null));
+ assertEntry(527798, 761, 78570, 652, history.getValues(i++, null));
+ assertEntry(527797, 760, 78570, 651, history.getValues(i++, null));
+ // Cycle point; start data normalization
+ assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
+ assertEntry(15015, 0, 23526, 0, history.getValues(i++, null));
+ assertEntry(124619, 0, 25179, 0, history.getValues(i++, null));
+ assertEntry(124618, 0, 25177, 0, history.getValues(i++, null));
+ assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
+ assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
+ // Anchor point; end data normalization
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(8289, 35, 6863, 38, history.getValues(i++, null));
+ assertEntry(113914, 174, 18364, 157, history.getValues(i++, null));
+ assertEntry(113913, 173, 18364, 157, history.getValues(i++, null));
+ // Cycle point
+ assertEntry(11378, 49, 9261, 49, history.getValues(i++, null));
+ assertEntry(11377, 48, 9261, 49, history.getValues(i++, null));
+ assertEntry(201765, 328, 41808, 291, history.getValues(i++, null));
+ assertEntry(201765, 328, 41807, 290, history.getValues(i++, null));
+ assertEntry(106106, 218, 39917, 201, history.getValues(i++, null));
+ assertEntry(106105, 217, 39917, 201, history.getValues(i++, null));
+
+ // Slice from middle should be augmented
+ history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS,
+ TIME_B + HOUR_IN_MILLIS); i = 0;
+ assertEntry(5338, 0, 6322, 0, history.getValues(i++, null));
+ assertEntry(5337, 0, 6320, 0, history.getValues(i++, null));
+ assertEntry(91686, 159, 18575, 146, history.getValues(i++, null));
+ assertEntry(91685, 159, 18575, 146, history.getValues(i++, null));
+ assertEquals(history.size(), i);
+ }
+ }
+
+ public void testAugmentPlanGigantic() throws Exception {
+ // We're in the future, but not that far off
+ setClock(Instant.parse("2012-06-01T00:00:00.00Z"));
+
+ // Create a simple history with a ton of measured usage
+ final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS);
+ final NetworkIdentitySet ident = new NetworkIdentitySet();
+ ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null,
+ false, true));
+ large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B,
+ new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0));
+
+ // Verify untouched total
+ assertEquals(12_730_893_164L, getHistory(large, null, TIME_A, TIME_C).getTotalBytes());
+
+ // Verify anchor that might cause overflows
+ final SubscriptionPlan plan = SubscriptionPlan.Builder
+ .createRecurringMonthly(ZonedDateTime.parse("2012-01-09T00:00:00.00Z"))
+ .setDataUsage(4_939_212_390L, TIME_B).build();
+ assertEquals(4_939_212_386L, getHistory(large, plan, TIME_A, TIME_C).getTotalBytes());
+ }
+
+ public void testRounding() throws Exception {
+ final NetworkStatsCollection coll = new NetworkStatsCollection(HOUR_IN_MILLIS);
+
+ // Special values should remain unchanged
+ for (long time : new long[] {
+ Long.MIN_VALUE, Long.MAX_VALUE, SubscriptionPlan.TIME_UNKNOWN
+ }) {
+ assertEquals(time, coll.roundUp(time));
+ assertEquals(time, coll.roundDown(time));
+ }
+
+ assertEquals(TIME_A, coll.roundUp(TIME_A));
+ assertEquals(TIME_A, coll.roundDown(TIME_A));
+
+ assertEquals(TIME_A + HOUR_IN_MILLIS, coll.roundUp(TIME_A + 1));
+ assertEquals(TIME_A, coll.roundDown(TIME_A + 1));
+
+ assertEquals(TIME_A, coll.roundUp(TIME_A - 1));
+ assertEquals(TIME_A - HOUR_IN_MILLIS, coll.roundDown(TIME_A - 1));
+ }
+
+ public void testMultiplySafe() {
+ assertEquals(25, multiplySafe(50, 1, 2));
+ assertEquals(100, multiplySafe(50, 2, 1));
+
+ assertEquals(-10, multiplySafe(30, -1, 3));
+ assertEquals(0, multiplySafe(30, 0, 3));
+ assertEquals(10, multiplySafe(30, 1, 3));
+ assertEquals(20, multiplySafe(30, 2, 3));
+ assertEquals(30, multiplySafe(30, 3, 3));
+ assertEquals(40, multiplySafe(30, 4, 3));
+
+ assertEquals(100_000_000_000L,
+ multiplySafe(300_000_000_000L, 10_000_000_000L, 30_000_000_000L));
+ assertEquals(100_000_000_010L,
+ multiplySafe(300_000_000_000L, 10_000_000_001L, 30_000_000_000L));
+ assertEquals(823_202_048L,
+ multiplySafe(4_939_212_288L, 2_121_815_528L, 12_730_893_165L));
+ }
+
/**
* Copy a {@link Resources#openRawResource(int)} into {@link File} for
* testing purposes.
@@ -235,28 +519,50 @@ public class NetworkStatsCollectionTest extends AndroidTestCase {
}
}
+ private static NetworkStatsHistory getHistory(NetworkStatsCollection collection,
+ SubscriptionPlan augmentPlan, long start, long end) {
+ return collection.getHistory(buildTemplateMobileAll(TEST_IMSI), augmentPlan, UID_ALL,
+ SET_ALL, TAG_NONE, FIELD_ALL, start, end, NetworkStatsAccess.Level.DEVICE, myUid());
+ }
+
private static void assertSummaryTotal(NetworkStatsCollection collection,
NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets,
@NetworkStatsAccess.Level int accessLevel) {
- final NetworkStats.Entry entry = collection.getSummary(
- template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel)
+ final NetworkStats.Entry actual = collection.getSummary(
+ template, Long.MIN_VALUE, Long.MAX_VALUE, accessLevel, myUid())
.getTotal(null);
- assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets);
+ assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual);
}
private static void assertSummaryTotalIncludingTags(NetworkStatsCollection collection,
NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- final NetworkStats.Entry entry = collection.getSummary(
- template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE)
+ final NetworkStats.Entry actual = collection.getSummary(
+ template, Long.MIN_VALUE, Long.MAX_VALUE, NetworkStatsAccess.Level.DEVICE, myUid())
.getTotalIncludingTags(null);
- assertEntry(entry, rxBytes, rxPackets, txBytes, txPackets);
+ assertEntry(rxBytes, rxPackets, txBytes, txPackets, actual);
+ }
+
+ private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets,
+ NetworkStats.Entry actual) {
+ assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual);
+ }
+
+ private static void assertEntry(long rxBytes, long rxPackets, long txBytes, long txPackets,
+ NetworkStatsHistory.Entry actual) {
+ assertEntry(new NetworkStats.Entry(rxBytes, rxPackets, txBytes, txPackets, 0L), actual);
+ }
+
+ private static void assertEntry(NetworkStats.Entry expected,
+ NetworkStatsHistory.Entry actual) {
+ assertEntry(expected, new NetworkStats.Entry(actual.rxBytes, actual.rxPackets,
+ actual.txBytes, actual.txPackets, 0L));
}
- private static void assertEntry(
- NetworkStats.Entry entry, long rxBytes, long rxPackets, long txBytes, long txPackets) {
- assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes);
- assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets);
- assertEquals("unexpected txBytes", txBytes, entry.txBytes);
- assertEquals("unexpected txPackets", txPackets, entry.txPackets);
+ private static void assertEntry(NetworkStats.Entry expected,
+ NetworkStats.Entry actual) {
+ assertEquals("unexpected rxBytes", expected.rxBytes, actual.rxBytes);
+ assertEquals("unexpected rxPackets", expected.rxPackets, actual.rxPackets);
+ assertEquals("unexpected txBytes", expected.txBytes, actual.txBytes);
+ assertEquals("unexpected txPackets", expected.txPackets, actual.txPackets);
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index fa997958ba6d..814a62663333 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -46,19 +46,17 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static com.android.internal.util.TestUtils.waitForIdleHandler;
+import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.AlarmManager;
import android.app.usage.NetworkStatsManager;
@@ -79,24 +77,21 @@ import android.net.NetworkTemplate;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.INetworkManagementService;
import android.os.IBinder;
+import android.os.INetworkManagementService;
import android.os.Looper;
-import android.os.Messenger;
-import android.os.MessageQueue;
-import android.os.MessageQueue.IdleHandler;
import android.os.Message;
+import android.os.Messenger;
import android.os.PowerManager;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
import android.util.TrustedTime;
import com.android.internal.net.VpnInfo;
import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.server.net.NetworkStatsService;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
@@ -112,9 +107,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
-import java.util.ArrayList;
import java.util.Objects;
-import java.util.List;
/**
* Tests for {@link NetworkStatsService}.
@@ -983,7 +976,7 @@ public class NetworkStatsServiceTest {
// verify summary API
final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end);
- assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
+ assertValues(stats, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
rxBytes, rxPackets, txBytes, txPackets, operations);
}
@@ -1107,28 +1100,25 @@ public class NetworkStatsServiceTest {
int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
long txPackets, int operations) {
final NetworkStats.Entry entry = new NetworkStats.Entry();
- List<Integer> sets = new ArrayList<>();
- if (set == SET_DEFAULT || set == SET_ALL) {
- sets.add(SET_DEFAULT);
- }
- if (set == SET_FOREGROUND || set == SET_ALL) {
- sets.add(SET_FOREGROUND);
+ final int[] sets;
+ if (set == SET_ALL) {
+ sets = new int[] { SET_ALL, SET_DEFAULT, SET_FOREGROUND };
+ } else {
+ sets = new int[] { set };
}
- List<Integer> roamings = new ArrayList<>();
- if (roaming == ROAMING_NO || roaming == ROAMING_ALL) {
- roamings.add(ROAMING_NO);
- }
- if (roaming == ROAMING_YES || roaming == ROAMING_ALL) {
- roamings.add(ROAMING_YES);
+ final int[] roamings;
+ if (roaming == ROAMING_ALL) {
+ roamings = new int[] { ROAMING_ALL, ROAMING_YES, ROAMING_NO };
+ } else {
+ roamings = new int[] { roaming };
}
- List<Integer> meterings = new ArrayList<>();
- if (metered == METERED_NO || metered == METERED_ALL) {
- meterings.add(METERED_NO);
- }
- if (metered == METERED_YES || metered == METERED_ALL) {
- meterings.add(METERED_YES);
+ final int[] meterings;
+ if (metered == METERED_ALL) {
+ meterings = new int[] { METERED_ALL, METERED_YES, METERED_NO };
+ } else {
+ meterings = new int[] { metered };
}
for (int s : sets) {