Fix Broken MessageQueueTests
Rewrite the addIdleHandler and removeIdleHandler tests to be more
clear.
Change-Id: I19547149d4cd85c535099ff5ca08703045ef73eb
diff --git a/tests/tests/os/src/android/os/cts/MessageQueueTest.java b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
index 95441ae..c7b549a 100644
--- a/tests/tests/os/src/android/os/cts/MessageQueueTest.java
+++ b/tests/tests/os/src/android/os/cts/MessageQueueTest.java
@@ -16,10 +16,7 @@
package android.os.cts;
-import dalvik.annotation.BrokenTest;
-import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargetNew;
import android.os.Handler;
import android.os.HandlerThread;
@@ -30,77 +27,92 @@
import android.os.MessageQueue.IdleHandler;
import android.test.AndroidTestCase;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
@TestTargetClass(MessageQueue.class)
public class MessageQueueTest extends AndroidTestCase {
- private boolean mResult;
- // Action flag: true means addIdleHanlder, false means removeIdleHanlder
- private boolean mActionFlag;
private static final long TIMEOUT = 1000;
- private static final long INTERVAL = 50;
- private IdleHandler mIdleHandler = new IdleHandler() {
- public boolean queueIdle() {
- MessageQueueTest.this.mResult = true;
- return true;
- }
- };
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mResult = false;
- }
+ public void testAddIdleHandler() throws InterruptedException {
+ TestLooperThread looperThread = new TestLooperThread(Test.ADD_IDLE_HANDLER);
+ looperThread.start();
- /**
- * After calling addIdleHandler (called by MessageQueueTestHelper#doTest), the size of
- * idleHanlder list is not 0 (before calling addIdleHandler, there is no idleHanlder in
- * the test looper we started, that means no idleHanlder with flag mResult), and in doTest,
- * we start a looper, which will queueIdle (Looper.loop()) if idleHanlder list has element,
- * then mResult will be set true. It can make sure addIdleHandler works. If no idleHanlder
- * with flag mResult, mResult will be false.
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- method = "addIdleHandler",
- args = {android.os.MessageQueue.IdleHandler.class}
- )
- @BrokenTest("needs investigation")
- public void testAddIdleHandler() throws RuntimeException, InterruptedException {
try {
- Looper.myQueue().addIdleHandler(null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
+ if (!looperThread.hasIdleHandlerBeenCalled()) {
+ fail("IdleHandler#queueIdle was NOT called: " + looperThread.getTestProgress());
+ }
+ } finally {
+ assertTrue("The looper should have been running.", looperThread.quit());
}
- // If mActionFlag is true, doTest will call addIdleHandler
- mActionFlag = true;
- mResult = false;
- MessageQueueTestHelper tester = new MessageQueueTestHelper();
- tester.doTest(TIMEOUT, INTERVAL);
-
- tester.quit();
- assertTrue(mResult);
}
- /**
- * In this test method, at the beginning of the LooperThread, we call addIdleHandler then
- * removeIdleHandler, there should be no element in idleHanlder list. So the Looper.loop()
- * will not call queueIdle(), mResult will not be set true.
- */
- @TestTargetNew(
- level = TestLevel.COMPLETE,
- method = "removeIdleHandler",
- args = {android.os.MessageQueue.IdleHandler.class}
- )
- @BrokenTest("needs investigation")
- public void testRemoveIdleHandler() throws RuntimeException, InterruptedException {
- mActionFlag = false;
- mResult = false;
- MessageQueueTestHelper tester = new MessageQueueTestHelper();
- tester.doTest(TIMEOUT, INTERVAL);
+ public void testRemoveIdleHandler() throws InterruptedException {
+ TestLooperThread looperThread = new TestLooperThread(Test.REMOVE_IDLE_HANDLER);
+ looperThread.start();
- tester.quit();
- assertFalse(mResult);
+ try {
+ if (looperThread.hasIdleHandlerBeenCalled()) {
+ fail("IdleHandler#queueIdle was called: " + looperThread.getTestProgress());
+ }
+ } finally {
+ assertTrue("The looper should have been running.", looperThread.quit());
+ }
+ }
+
+ private enum Test {ADD_IDLE_HANDLER, REMOVE_IDLE_HANDLER};
+
+ /**
+ * {@link HandlerThread} that adds or removes an idle handler depending on the {@link Test}
+ * given. It uses a {@link CountDownLatch} with an initial count of 2. The first count down
+ * occurs right before the looper's run thread had started running. The final count down
+ * occurs when the idle handler was executed. Tests can call {@link #hasIdleHandlerBeenCalled()}
+ * to see if the countdown reached to 0 or not.
+ */
+ private static class TestLooperThread extends HandlerThread {
+
+ private final Test mTestMode;
+
+ private final CountDownLatch mIdleLatch = new CountDownLatch(2);
+
+ TestLooperThread(Test testMode) {
+ super("TestLooperThread");
+ mTestMode = testMode;
+ }
+
+ @Override
+ protected void onLooperPrepared() {
+ super.onLooperPrepared();
+
+ IdleHandler idleHandler = new IdleHandler() {
+ public boolean queueIdle() {
+ mIdleLatch.countDown();
+ return false;
+ }
+ };
+
+ if (mTestMode == Test.ADD_IDLE_HANDLER) {
+ Looper.myQueue().addIdleHandler(idleHandler);
+ } else {
+ Looper.myQueue().addIdleHandler(idleHandler);
+ Looper.myQueue().removeIdleHandler(idleHandler);
+ }
+ }
+
+ @Override
+ public void run() {
+ mIdleLatch.countDown();
+ super.run();
+ }
+
+ public boolean hasIdleHandlerBeenCalled() throws InterruptedException {
+ return mIdleLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
+ }
+
+ public long getTestProgress() {
+ return mIdleLatch.getCount();
+ }
}
/**
@@ -155,68 +167,6 @@
}
/**
- * Helper class used to test addIdleHandler, removeIdleHandler
- */
- private class MessageQueueTestHelper {
-
- private boolean mDone;
- private Looper mLooper;
-
- public void doTest(long timeout, long interval) throws InterruptedException {
- (new LooperThread()).start();
- synchronized (this) {
- long now = System.currentTimeMillis();
- long endTime = now + timeout;
- // Wait and frequently check if mDone is set.
- while (!mDone && now < endTime) {
- wait(interval);
- now = System.currentTimeMillis();
- }
- }
- mLooper.quit();
- if (!mDone) {
- throw new RuntimeException("test timed out");
- }
- }
-
- private class LooperThread extends HandlerThread {
- public LooperThread() {
- super("MessengeQueueLooperThread");
- }
-
- public void onLooperPrepared() {
- mLooper = getLooper();
- if (mActionFlag) {
- // If mActionFlag is true, just addIdleHandler, and
- // Looper.loop() will set mResult true.
- Looper.myQueue().addIdleHandler(mIdleHandler);
- } else {
- // If mActionFlag is false, addIdleHandler and remove it, then Looper.loop()
- // will not set mResult true because the idleHandler list is empty.
- Looper.myQueue().addIdleHandler(mIdleHandler);
- Looper.myQueue().removeIdleHandler(mIdleHandler);
- }
- }
-
- @Override
- public void run() {
- super.run();
- synchronized (MessageQueueTestHelper.this) {
- mDone = true;
- MessageQueueTestHelper.this.notifyAll();
- }
- }
- }
-
- public void quit() {
- synchronized (this) {
- mDone = true;
- notifyAll();
- }
- }
- }
-
- /**
* Helper class used to test sending message to message queue.
*/
private class OrderTestHelper {