Merge "Networking unit tests: fix some flaky tests" am: 501bae6492
am: b87cf12ad3

Change-Id: Id95a8ef670b8f84664c518d19df449720ae90eb2
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index adf6998..f77608f 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -349,7 +349,6 @@
                 chan.connect(mContext, this, msg.replyTo);
                 chan.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
             }
-
         }
 
         public static MockServiceHandler create(Context context) {
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
index 3957cb0..d46facf 100644
--- a/tests/net/java/android/net/util/SharedLogTest.java
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -33,8 +33,8 @@
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class SharedLogTest {
-    private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}\\.\\d{3}";
-    private static final String TIMESTAMP = "HH:MM:SS.xxx";
+    private static final String TIMESTAMP_PATTERN = "\\d{2}:\\d{2}:\\d{2}";
+    private static final String TIMESTAMP = "HH:MM:SS";
 
     @Test
     public void testBasicOperation() {
@@ -85,7 +85,7 @@
             String got = lines[i];
             String want = expected[i];
             assertTrue(String.format("'%s' did not contain '%s'", got, want), got.endsWith(want));
-            assertTrue(String.format("'%s' did not contain a HH:MM:SS.xxx timestamp", got),
+            assertTrue(String.format("'%s' did not contain a %s timestamp", got, TIMESTAMP),
                     got.replaceFirst(TIMESTAMP_PATTERN, TIMESTAMP).contains(TIMESTAMP));
         }
     }
diff --git a/tests/net/java/com/android/internal/util/TestUtils.java b/tests/net/java/com/android/internal/util/TestUtils.java
new file mode 100644
index 0000000..c9fa340
--- /dev/null
+++ b/tests/net/java/com/android/internal/util/TestUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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.internal.util;
+
+import static org.junit.Assert.fail;
+
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+
+public final class TestUtils {
+    private TestUtils() { }
+
+    /**
+     * Block until the given Handler thread becomes idle, or until timeoutMs has passed.
+     */
+    public static void waitForIdleHandler(HandlerThread handlerThread, long timeoutMs) {
+        // TODO: convert to getThreadHandler once it is available on aosp
+        waitForIdleLooper(handlerThread.getLooper(), timeoutMs);
+    }
+
+    /**
+     * Block until the given Looper becomes idle, or until timeoutMs has passed.
+     */
+    public static void waitForIdleLooper(Looper looper, long timeoutMs) {
+        waitForIdleHandler(new Handler(looper), timeoutMs);
+    }
+
+    /**
+     * Block until the given Handler becomes idle, or until timeoutMs has passed.
+     */
+    public static void waitForIdleHandler(Handler handler, long timeoutMs) {
+        final ConditionVariable cv = new ConditionVariable();
+        handler.post(() -> cv.open());
+        if (!cv.block(timeoutMs)) {
+            fail(handler.toString() + " did not become idle after " + timeoutMs + " ms");
+        }
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 198ddc6..b8ac31d 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,6 +23,8 @@
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.NetworkCapabilities.*;
 
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
+
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.eq;
@@ -212,20 +214,8 @@
         }
     }
 
-    /**
-     * Block until the given handler becomes idle, or until timeoutMs has passed.
-     */
-    private static void waitForIdleHandler(HandlerThread handlerThread, int timeoutMs) {
-        final ConditionVariable cv = new ConditionVariable();
-        final Handler handler = new Handler(handlerThread.getLooper());
-        handler.post(() -> cv.open());
-        if (!cv.block(timeoutMs)) {
-            fail("HandlerThread " + handlerThread.getName() +
-                    " did not become idle after " + timeoutMs + " ms");
-        }
-    }
-
-    public void waitForIdle(int timeoutMs) {
+    public void waitForIdle(int timeoutMsAsInt) {
+        long timeoutMs = timeoutMsAsInt;
         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
         waitForIdle(mCellNetworkAgent, timeoutMs);
         waitForIdle(mWiFiNetworkAgent, timeoutMs);
@@ -233,7 +223,7 @@
         waitForIdleHandler(mService.mHandlerThread, timeoutMs);
     }
 
-    public void waitForIdle(MockNetworkAgent agent, int timeoutMs) {
+    public void waitForIdle(MockNetworkAgent agent, long timeoutMs) {
         if (agent == null) {
             return;
         }
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 92dcdac..2be5dae 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -27,6 +27,8 @@
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
+import static com.android.internal.util.TestUtils.waitForIdleHandler;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -56,7 +58,6 @@
 
 import com.android.internal.net.VpnInfo;
 import com.android.server.net.NetworkStatsService;
-import com.android.server.net.NetworkStatsServiceTest.IdleableHandlerThread;
 import com.android.server.net.NetworkStatsServiceTest.LatchedHandler;
 
 import java.util.ArrayList;
@@ -102,7 +103,7 @@
 
     private long mElapsedRealtime;
 
-    private IdleableHandlerThread mObserverHandlerThread;
+    private HandlerThread mObserverHandlerThread;
     private Handler mObserverNoopHandler;
 
     private LatchedHandler mHandler;
@@ -118,7 +119,7 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mObserverHandlerThread = new IdleableHandlerThread("HandlerThread");
+        mObserverHandlerThread = new HandlerThread("HandlerThread");
         mObserverHandlerThread.start();
         final Looper observerLooper = mObserverHandlerThread.getLooper();
         mStatsObservers = new NetworkStatsObservers() {
@@ -319,7 +320,7 @@
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
         waitForObserverToIdle();
-        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
     }
 
     @Test
@@ -356,7 +357,7 @@
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
         waitForObserverToIdle();
-        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
     }
 
     @Test
@@ -429,7 +430,7 @@
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
         waitForObserverToIdle();
-        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.mLastMessageType);
+        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, mHandler.lastMessageType);
     }
 
     @Test
@@ -470,19 +471,7 @@
     }
 
     private void waitForObserverToIdle() {
-        waitForIdleLooper(mObserverHandlerThread.getLooper(), WAIT_TIMEOUT_MS);
-        waitForIdleLooper(mHandler.getLooper(), WAIT_TIMEOUT_MS);
+        waitForIdleHandler(mObserverHandlerThread, WAIT_TIMEOUT_MS);
+        waitForIdleHandler(mHandler, WAIT_TIMEOUT_MS);
     }
-
-    // TODO: unify with ConnectivityService.waitForIdleHandler and
-    // NetworkServiceStatsTest.IdleableHandlerThread
-    private static void waitForIdleLooper(Looper looper, long timeoutMs) {
-        final ConditionVariable cv = new ConditionVariable();
-        final Handler handler = new Handler(looper);
-        handler.post(() -> cv.open());
-        if (!cv.block(timeoutMs)) {
-            fail("Looper did not become idle after " + timeoutMs + " ms");
-        }
-    }
-
 }
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 029693f..feb46d3 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -45,6 +45,7 @@
 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 org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -154,7 +155,7 @@
     private @Mock IConnectivityManager mConnManager;
     private @Mock IBinder mBinder;
     private @Mock AlarmManager mAlarmManager;
-    private IdleableHandlerThread mHandlerThread;
+    private HandlerThread mHandlerThread;
     private Handler mHandler;
 
     private NetworkStatsService mService;
@@ -181,7 +182,7 @@
                 mServiceContext, mNetManager, mAlarmManager, wakeLock, mTime,
                 TelephonyManager.getDefault(), mSettings, new NetworkStatsObservers(),
                 mStatsDir, getBaseDir(mStatsDir));
-        mHandlerThread = new IdleableHandlerThread("HandlerThread");
+        mHandlerThread = new HandlerThread("HandlerThread");
         mHandlerThread.start();
         Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService);
         mHandler = new Handler(mHandlerThread.getLooper(), callback);
@@ -886,7 +887,7 @@
 
         // Send dummy message to make sure that any previous message has been handled
         mHandler.sendMessage(mHandler.obtainMessage(-1));
-        mHandlerThread.waitForIdle(WAIT_TIMEOUT);
+        waitForIdleHandler(mHandler, WAIT_TIMEOUT);
 
 
 
@@ -908,7 +909,7 @@
         assertNetworkTotal(sTemplateWifi, 1024L, 1L, 2048L, 2L, 0);
 
         // make sure callback has not being called
-        assertEquals(INVALID_TYPE, latchedHandler.mLastMessageType);
+        assertEquals(INVALID_TYPE, latchedHandler.lastMessageType);
 
         // and bump forward again, with counters going higher. this is
         // important, since it will trigger the data usage callback
@@ -926,7 +927,7 @@
 
         // Wait for the caller to ack receipt of CALLBACK_LIMIT_REACHED
         assertTrue(cv.block(WAIT_TIMEOUT));
-        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.mLastMessageType);
+        assertEquals(NetworkStatsManager.CALLBACK_LIMIT_REACHED, latchedHandler.lastMessageType);
         cv.close();
 
         // Allow binder to disconnect
@@ -937,7 +938,7 @@
 
         // Wait for the caller to ack receipt of CALLBACK_RELEASED
         assertTrue(cv.block(WAIT_TIMEOUT));
-        assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.mLastMessageType);
+        assertEquals(NetworkStatsManager.CALLBACK_RELEASED, latchedHandler.lastMessageType);
 
         // Make sure that the caller binder gets disconnected
         verify(mBinder).unlinkToDeath(any(IBinder.DeathRecipient.class), anyInt());
@@ -1203,12 +1204,12 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
         // Send dummy message to make sure that any previous message has been handled
         mHandler.sendMessage(mHandler.obtainMessage(-1));
-        mHandlerThread.waitForIdle(WAIT_TIMEOUT);
+        waitForIdleHandler(mHandler, WAIT_TIMEOUT);
     }
 
     static class LatchedHandler extends Handler {
         private final ConditionVariable mCv;
-        int mLastMessageType = INVALID_TYPE;
+        int lastMessageType = INVALID_TYPE;
 
         LatchedHandler(Looper looper, ConditionVariable cv) {
             super(looper);
@@ -1217,49 +1218,9 @@
 
         @Override
         public void handleMessage(Message msg) {
-            mLastMessageType = msg.what;
+            lastMessageType = msg.what;
             mCv.open();
             super.handleMessage(msg);
         }
     }
-
-    /**
-     * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
-     * will return immediately if the handler is already idle.
-     */
-    static class IdleableHandlerThread extends HandlerThread {
-        private IdleHandler mIdleHandler;
-
-        public IdleableHandlerThread(String name) {
-            super(name);
-        }
-
-        public void waitForIdle(long timeoutMs) {
-            final ConditionVariable cv = new ConditionVariable();
-            final MessageQueue queue = getLooper().getQueue();
-
-            synchronized (queue) {
-                if (queue.isIdle()) {
-                    return;
-                }
-
-                assertNull("BUG: only one idle handler allowed", mIdleHandler);
-                mIdleHandler = new IdleHandler() {
-                    public boolean queueIdle() {
-                        cv.open();
-                        mIdleHandler = null;
-                        return false;  // Remove the handler.
-                    }
-                };
-                queue.addIdleHandler(mIdleHandler);
-            }
-
-            if (!cv.block(timeoutMs)) {
-                fail("HandlerThread " + getName() + " did not become idle after " + timeoutMs
-                        + " ms");
-                queue.removeIdleHandler(mIdleHandler);
-            }
-        }
-    }
-
 }