Index: mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java |
diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java |
index f976e590da3f803dbcf1b24d70bf1b3ba6417640..e6140086c2c562facb8c13735dd327f11a7c1b99 100644 |
--- a/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java |
+++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/RouterTest.java |
@@ -10,6 +10,8 @@ import org.chromium.mojo.MojoTestCase; |
import org.chromium.mojo.bindings.BindingsTestUtils.CapturingErrorHandler; |
import org.chromium.mojo.bindings.BindingsTestUtils.RecordingMessageReceiverWithResponder; |
import org.chromium.mojo.system.Core; |
+import org.chromium.mojo.system.Core.HandleSignals; |
+import org.chromium.mojo.system.Core.WaitResult; |
import org.chromium.mojo.system.Handle; |
import org.chromium.mojo.system.MessagePipeHandle; |
import org.chromium.mojo.system.MojoResult; |
@@ -91,17 +93,16 @@ public class RouterTest extends MojoTestCase { |
} |
/** |
- * Testing receiving a message via the router that expected a response. |
+ * Sends a message to the Router. |
+ * |
+ * @param messageIndex Used when sending multiple messages to indicate the index of this |
+ * message. |
+ * @param requestMessageType The message type to use in the header of the sent message. |
+ * @param requestId The requestId to use in the header of the sent message. |
*/ |
- @SmallTest |
- public void testReceivingViaRouterWithResponse() { |
- final int requestMessageType = 0xdead; |
- final int responseMessageType = 0xbeef; |
- final int requestId = 0xdeadbeaf; |
- |
- // Sending a message expecting a response. |
- MessageHeader header = new MessageHeader(requestMessageType, |
- MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, requestId); |
+ private void sendMessageToRouter(int messageIndex, int requestMessageType, int requestId) { |
+ MessageHeader header = new MessageHeader( |
+ requestMessageType, MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, requestId); |
Encoder encoder = new Encoder(CoreImpl.getInstance(), header.getSize()); |
header.encode(encoder); |
Message headerMessage = encoder.getMessage(); |
@@ -109,18 +110,32 @@ public class RouterTest extends MojoTestCase { |
MessagePipeHandle.WriteFlags.NONE); |
runLoopUntilIdle(); |
- assertEquals(1, mReceiver.messagesWithReceivers.size()); |
+ assertEquals(messageIndex + 1, mReceiver.messagesWithReceivers.size()); |
Pair<Message, MessageReceiver> receivedMessage = |
- mReceiver.messagesWithReceivers.get(0); |
+ mReceiver.messagesWithReceivers.get(messageIndex); |
assertEquals(headerMessage.getData(), receivedMessage.first.getData()); |
+ } |
- // Sending the response. |
- MessageHeader responseHeader = new MessageHeader(responseMessageType, |
- MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG, requestId); |
- encoder = new Encoder(CoreImpl.getInstance(), header.getSize()); |
+ /** |
+ * Sends a response message from the Router. |
+ * |
+ * @param messageIndex Used when sending responses to multiple messages to indicate the index |
+ * of the message that this message is a response to. |
+ * @param responseMessageType The message type to use in the header of the response message. |
+ */ |
+ private void sendResponseFromRouter(int messageIndex, int responseMessageType) { |
+ Pair<Message, MessageReceiver> receivedMessage = |
+ mReceiver.messagesWithReceivers.get(messageIndex); |
+ |
+ long requestId = receivedMessage.first.asServiceMessage().getHeader().getRequestId(); |
+ |
+ MessageHeader responseHeader = new MessageHeader( |
+ responseMessageType, MessageHeader.MESSAGE_IS_RESPONSE_FLAG, requestId); |
+ Encoder encoder = new Encoder(CoreImpl.getInstance(), responseHeader.getSize()); |
responseHeader.encode(encoder); |
Message message = encoder.getMessage(); |
receivedMessage.second.accept(message); |
+ |
ByteBuffer receivedResponseMessage = ByteBuffer.allocateDirect(responseHeader.getSize()); |
ResultAnd<MessagePipeHandle.ReadMessageResult> result = |
mHandle.readMessage(receivedResponseMessage, 0, MessagePipeHandle.ReadFlags.NONE); |
@@ -128,4 +143,90 @@ public class RouterTest extends MojoTestCase { |
assertEquals(MojoResult.OK, result.getMojoResult()); |
assertEquals(message.getData(), receivedResponseMessage); |
} |
+ |
+ /** |
+ * Clears {@code mReceiver.messagesWithReceivers} allowing all message receivers to be |
+ * finalized. |
+ * <p> |
+ * Since there is no way to force the Garbage Collector to actually call finalize and we want to |
+ * test the effects of the finalize() method, we explicitly call finalize() on all of the |
+ * message receivers. We do this in a custom thread to better approximate what the JVM does. |
+ */ |
+ private void clearAllMessageReceivers() { |
+ Thread myFinalizerThread = new Thread() { |
+ @Override |
+ public void run() { |
+ for (Pair<Message, MessageReceiver> receivedMessage : |
+ mReceiver.messagesWithReceivers) { |
+ RouterImpl.ResponderThunk thunk = |
+ (RouterImpl.ResponderThunk) receivedMessage.second; |
+ try { |
+ thunk.finalize(); |
+ } catch (Throwable e) { |
+ throw new RuntimeException(e); |
+ } |
+ } |
+ } |
+ }; |
+ myFinalizerThread.start(); |
+ try { |
+ myFinalizerThread.join(); |
+ } catch (InterruptedException e) { |
+ // ignore. |
+ } |
+ mReceiver.messagesWithReceivers.clear(); |
+ } |
+ |
+ /** |
+ * Testing receiving a message via the router that expected a response. |
+ */ |
+ @SmallTest |
+ public void testReceivingViaRouterWithResponse() { |
+ final int requestMessageType = 0xdead; |
+ final int responseMessageType = 0xbeef; |
+ final int requestId = 0xdeadbeaf; |
+ |
+ // Send a message expecting a response. |
+ sendMessageToRouter(0, requestMessageType, requestId); |
+ |
+ // Sending the response. |
+ sendResponseFromRouter(0, responseMessageType); |
+ } |
+ |
+ /** |
+ * Tests that if a callback is dropped (i.e. becomes unreachable and is finalized |
+ * without being used), then the message pipe will be closed. |
+ */ |
+ @SmallTest |
+ public void testDroppingReceiverWithoutUsingIt() { |
+ // Send 10 messages to the router without sending a response. |
+ for (int i = 0; i < 10; i++) { |
+ sendMessageToRouter(i, i, i); |
+ } |
+ |
+ // Now send the 10 responses. This should work fine. |
+ for (int i = 0; i < 10; i++) { |
+ sendResponseFromRouter(i, i); |
+ } |
+ |
+ // Clear all MessageRecievers so that the ResponderThunks will |
+ // be finalized. |
+ clearAllMessageReceivers(); |
+ |
+ // Send another message to the router without sending a response. |
+ sendMessageToRouter(0, 0, 0); |
+ |
+ // Clear the MessageReciever so that the ResponderThunk will |
+ // be finalized. Since the RespondeThunk was never used, this |
+ // should close the pipe. |
+ clearAllMessageReceivers(); |
+ // The close() occurs asynchronously on this thread. |
+ runLoopUntilIdle(); |
+ |
+ // Confirm that the pipe was closed on the Router side. |
+ HandleSignals closedFlag = HandleSignals.none().setPeerClosed(true); |
+ WaitResult result = mHandle.wait(closedFlag, 0); |
+ assertEquals(MojoResult.OK, result.getMojoResult()); |
+ assertEquals(closedFlag, result.getHandleSignalsState().getSatisfiedSignals()); |
+ } |
} |