blob: 81467be7fc3c75964c2a7c05b08e3032ad6a5d90 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.media.router.cast;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.media.router.CastSessionUtil;
import org.chromium.chrome.browser.media.router.ClientRecord;
import org.chromium.chrome.browser.media.router.JSONTestUtils.JSONObjectLike;
import org.chromium.chrome.browser.media.router.JSONTestUtils.JSONStringLike;
import org.chromium.chrome.browser.media.router.cast.CastMessageHandler.RequestRecord;
import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Robolectric tests for CastSession.
*/
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class CastMessageHandlerTest {
private static final String TAG = "MediaRouter";
private static final String SESSION_ID = "SESSION_ID";
private static final String INVALID_SESSION_ID = "INVALID_SESSION_ID";
private static final String CLIENT_ID1 = "00000000000000001";
private static final String CLIENT_ID2 = "00000000000000002";
private static final String INVALID_CLIENT_ID = "xxxxxxxxxxxxxxxxx";
private static final String NAMESPACE1 = "namespace1";
private static final String NAMESPACE2 = "namespace2";
private static final String MEDIA_NAMESPACE = CastSessionUtil.MEDIA_NAMESPACE;
private static final int SEQUENCE_NUMBER1 = 1;
private static final int SEQUENCE_NUMBER2 = 2;
private static final int REQUEST_ID1 = 1;
private static final int REQUEST_ID2 = 2;
private static final int INVALID_SEQUENCE_NUMBER =
CastMessageHandler.INVALID_SEQUENCE_NUMBER;
private CastMediaRouteProvider mRouteProvider;
private CastSession mSession;
private CastMessageHandler mMessageHandler;
private int mNumStopApplicationCalled;
private interface CheckedRunnable { void run() throws Exception; }
@Before
public void setUp() {
ShadowLog.stream = System.out;
mRouteProvider = mock(CastMediaRouteProvider.class);
mSession = mock(CastSession.class);
doReturn(SESSION_ID).when(mSession).getSessionId();
doReturn(true).when(mSession).sendStringCastMessage(
anyString(), anyString(), anyString(), anyInt());
mMessageHandler = spy(new CastMessageHandler(mRouteProvider));
mMessageHandler.onSessionCreated(mSession);
final Set<String> clientIds = new HashSet<String>();
clientIds.add(CLIENT_ID1);
clientIds.add(CLIENT_ID2);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) {
return clientIds;
}
})
.when(mRouteProvider)
.getClients();
doNothing().when(mRouteProvider).onMessage(anyString(), anyString());
}
void setUpForAppMessageTest() throws JSONException {
Set<String> namespaces = new HashSet<String>();
namespaces.add(NAMESPACE1);
doReturn(namespaces).when(mSession).getNamespaces();
doReturn(true).when(mMessageHandler)
.sendJsonCastMessage(any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testOnSessionCreated() {
Map<String, ClientRecord> clientRecords = new HashMap<String, ClientRecord>();
clientRecords.put(CLIENT_ID1, new ClientRecord(
"DONTCARE", CLIENT_ID1, "DONTCARE", "DONTCARE", "DONTCARE", 0));
clientRecords.put(CLIENT_ID2, new ClientRecord(
"DONTCARE", CLIENT_ID2, "DONTCARE", "DONTCARE", "DONTCARE", 0));
clientRecords.get(CLIENT_ID1).isConnected = true;
doReturn(clientRecords).when(mRouteProvider).getClientRecords();
// The call in setUp() actually only sets the session. This call will notify the clients
// that have sent "client_connect"
mMessageHandler.onSessionCreated(mSession);
verify(mSession).onClientConnected(CLIENT_ID1);
verify(mSession, never()).onClientConnected(CLIENT_ID2);
}
@Test
@Feature({"MediaRouter"})
public void testHandleSessionMessageOfV2MessageType() throws JSONException {
doReturn(true).when(mMessageHandler).handleCastV2Message(any(JSONObject.class));
JSONObject message = new JSONObject();
message.put("type", "v2_message");
assertTrue(mMessageHandler.handleSessionMessage(message));
verify(mMessageHandler).handleCastV2Message(argThat(new JSONObjectLike(message)));
}
@Test
@Feature({"MediaRouter"})
public void testHandleSessionMessageOfAppMessageType() throws JSONException {
doReturn(true).when(mMessageHandler).handleAppMessage(any(JSONObject.class));
JSONObject message = new JSONObject();
message.put("type", "app_message");
assertTrue(mMessageHandler.handleSessionMessage(message));
verify(mMessageHandler).handleAppMessage(argThat(new JSONObjectLike(message)));
}
@Test
@Feature({"MediaRouter"})
public void testHandleSessionMessageOfUnsupportedType() throws JSONException {
doReturn(true).when(mMessageHandler).handleCastV2Message(any(JSONObject.class));
JSONObject message = new JSONObject();
message.put("type", "unsupported");
assertFalse(mMessageHandler.handleSessionMessage(message));
verify(mMessageHandler, never()).handleCastV2Message(any(JSONObject.class));
verify(mMessageHandler, never()).handleAppMessage(any(JSONObject.class));
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageWithWrongTypeInnerMessage() throws JSONException {
JSONObject innerMessage = new JSONObject()
.put("type", "STOP");
final JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
// Replace the inner JSON message with string.
message.put("message", "wrong type inner message");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleCastV2Message(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).handleStopMessage(anyString(), anyInt());
verify(mSession, never()).handleVolumeMessage(any(JSONObject.class), anyString(), anyInt());
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageOfStopType() throws JSONException {
JSONObject innerMessage = new JSONObject()
.put("type", "STOP");
JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
assertTrue(mMessageHandler.handleCastV2Message(message));
verify(mMessageHandler).handleStopMessage(eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageofSetVolumeTypeShouldWait() throws JSONException {
doReturn(new CastSession.HandleVolumeMessageResult(true, true))
.when(mSession).handleVolumeMessage(any(JSONObject.class), anyString(), anyInt());
JSONObject innerMessage = new JSONObject()
.put("type", "SET_VOLUME")
.put("volume", new JSONObject()
.put("level", (double) 1)
.put("muted", false));
JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
assertTrue(mMessageHandler.handleCastV2Message(message));
JSONObject volumeMessage = innerMessage.getJSONObject("volume");
verify(mSession).handleVolumeMessage(
argThat(new JSONObjectLike(innerMessage.getJSONObject("volume"))),
eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
assertEquals(mMessageHandler.getVolumeRequestsForTest().size(), 1);
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageofSetVolumeTypeShouldNotWait() throws JSONException {
doReturn(new CastSession.HandleVolumeMessageResult(true, false))
.when(mSession).handleVolumeMessage(any(JSONObject.class), anyString(), anyInt());
JSONObject innerMessage = new JSONObject()
.put("type", "SET_VOLUME")
.put("volume", new JSONObject()
.put("level", (double) 1)
.put("muted", false));
JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
assertTrue(mMessageHandler.handleCastV2Message(message));
JSONObject volumeMessage = innerMessage.getJSONObject("volume");
verify(mSession).handleVolumeMessage(
argThat(new JSONObjectLike(innerMessage.getJSONObject("volume"))),
eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
assertEquals(mMessageHandler.getVolumeRequestsForTest().size(), 0);
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageofSetVolumeTypeWithNullVolumeMessage() throws JSONException {
JSONObject innerMessage = new JSONObject()
.put("type", "SET_VOLUME");
final JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleCastV2Message(message);
}
}, JSONException.class);
verify(mSession, never()).handleVolumeMessage(any(JSONObject.class), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageofSetVolumeTypeWithWrongTypeVolumeMessage() throws JSONException {
JSONObject innerMessage = new JSONObject()
.put("type", "SET_VOLUME")
.put("volume", "wrong type volume message");
final JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleCastV2Message(message);
}
}, JSONException.class);
verify(mSession, never()).handleVolumeMessage(any(JSONObject.class), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageOfMediaMessageType() throws JSONException {
doReturn(true).when(mMessageHandler).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
for (String messageType : CastMessageHandler.getMediaMessageTypesForTest()) {
// TODO(zqzhang): SET_VOLUME and STOP should not reach here?
if ("MEDIA_SET_VOLUME".equals(messageType) || "STOP_MEDIA".equals(messageType)) {
continue;
}
JSONObject innerMessage = new JSONObject().put("type", messageType);
JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
assertTrue(mMessageHandler.handleCastV2Message(message));
JSONObject expected = new JSONObject();
if (CastMessageHandler.getMediaOverloadedMessageTypesForTest()
.containsKey(messageType)) {
expected.put("type", CastMessageHandler.getMediaOverloadedMessageTypesForTest()
.get(messageType));
} else {
expected.put("type", messageType);
}
verify(mMessageHandler)
.sendJsonCastMessage(argThat(new JSONObjectLike(expected)),
eq(CastSessionUtil.MEDIA_NAMESPACE), eq(CLIENT_ID1),
eq(SEQUENCE_NUMBER1));
}
}
@Test
@Feature({"MediaRouter"})
public void testCastV2MessageWithNullSequenceNumber() throws JSONException {
JSONObject innerMessage = new JSONObject()
.put("type", "STOP");
JSONObject message = buildCastV2Message(CLIENT_ID1, innerMessage);
message.remove("sequenceNumber");
assertTrue(mMessageHandler.handleCastV2Message(message));
verify(mMessageHandler).handleStopMessage(eq(CLIENT_ID1), eq(INVALID_SEQUENCE_NUMBER));
}
@Test
@Feature({"MediaRouter"})
public void testHandleStopMessage() throws JSONException {
assertEquals(0, mMessageHandler.getStopRequestsForTest().size());
mMessageHandler.handleStopMessage(CLIENT_ID1, SEQUENCE_NUMBER1);
assertEquals(1, mMessageHandler.getStopRequestsForTest().get(CLIENT_ID1).size(), 1);
verify(mSession).stopApplication();
mMessageHandler.handleStopMessage(CLIENT_ID1, SEQUENCE_NUMBER2);
assertEquals(2, mMessageHandler.getStopRequestsForTest().get(CLIENT_ID1).size(), 2);
verify(mSession, times(2)).stopApplication();
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithExistingNamespace() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
assertTrue(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler).sendJsonCastMessage(
argThat(new JSONObjectLike(actualMessage)), eq(NAMESPACE1),
eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNonexistingNamespace() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE2, actualMessage);
assertFalse(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithoutSequenceNumber() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.remove("sequenceNumber");
assertTrue(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler).sendJsonCastMessage(
argThat(new JSONObjectLike(actualMessage)), eq(NAMESPACE1),
eq(CLIENT_ID1), eq(INVALID_SEQUENCE_NUMBER));
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNullSessionId() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.getJSONObject("message").remove("sessionId");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithWrongSessionId() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.getJSONObject("message").put("sessionId", INVALID_SESSION_ID);
assertFalse(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNullActualMessage() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.getJSONObject("message").remove("message");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithStringMessage() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.getJSONObject("message").put("message", "string message");
assertTrue(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
verify(mSession).sendStringCastMessage(
eq("string message"), eq(NAMESPACE1), eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNullAppMessage() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.remove("message");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithEmptyAppMessage() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.put("message", new JSONObject());
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithWrongTypeAppMessage() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.put("message", "wrong type app message");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNullClient() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
final JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.remove("clientId");
expectException(new CheckedRunnable() {
@Override
public void run() throws Exception {
mMessageHandler.handleAppMessage(message);
}
}, JSONException.class);
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testAppMessageWithNonexistingClient() throws JSONException {
setUpForAppMessageTest();
JSONObject actualMessage = buildActualAppMessage();
JSONObject message = buildAppMessage(CLIENT_ID1, NAMESPACE1, actualMessage);
message.put("clientId", INVALID_CLIENT_ID);
assertFalse(mMessageHandler.handleAppMessage(message));
verify(mMessageHandler, never()).sendJsonCastMessage(
any(JSONObject.class), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testSendJsonCastMessage() throws JSONException {
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
JSONObject message = buildJsonCastMessage("message");
assertTrue(mMessageHandler.sendJsonCastMessage(
message, NAMESPACE1, CLIENT_ID1, SEQUENCE_NUMBER1));
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
verify(mSession).sendStringCastMessage(
argThat(new JSONStringLike(message)), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testSendJsonCastMessageWhenApiClientInvalid() throws JSONException {
doReturn(true).when(mSession).isApiClientInvalid();
JSONObject message = buildJsonCastMessage("message");
assertFalse(mMessageHandler.sendJsonCastMessage(
message, NAMESPACE1, CLIENT_ID1, SEQUENCE_NUMBER1));
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
verify(mSession, never()).sendStringCastMessage(
anyString(), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testSendJsonCastMessageWithInvalidSequenceNumber() throws JSONException {
JSONObject message = buildJsonCastMessage("message");
assertTrue(mMessageHandler.sendJsonCastMessage(
message, NAMESPACE1, CLIENT_ID1, INVALID_SEQUENCE_NUMBER));
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
verify(mSession).sendStringCastMessage(
argThat(new JSONStringLike(message)), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testSendJsonCastMessageWithNullRequestId() throws JSONException {
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
JSONObject message = buildJsonCastMessage("message");
message.remove("requestId");
assertTrue(mMessageHandler.sendJsonCastMessage(
message, NAMESPACE1, CLIENT_ID1, SEQUENCE_NUMBER1));
assertTrue(message.has("requestId"));
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
verify(mSession).sendStringCastMessage(
argThat(new JSONStringLike(message)), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testOnMessageReceivedWithExistingRequestId() throws JSONException {
doNothing().when(mMessageHandler).onAppMessage(
anyString(), anyString(), any(RequestRecord.class));
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.getRequestsForTest().append(
REQUEST_ID1, request);
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
JSONObject message = new JSONObject();
message.put("requestId", REQUEST_ID1);
mMessageHandler.onMessageReceived(NAMESPACE1, message.toString());
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
verify(mMessageHandler).onAppMessage(eq(message.toString()), eq(NAMESPACE1), eq(request));
}
@Test
@Feature({"MediaRouter"})
public void testOnMessageReceivedWithNonexistingRequestId() throws JSONException {
doNothing().when(mMessageHandler).onAppMessage(
anyString(), anyString(), any(RequestRecord.class));
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.getRequestsForTest().append(
REQUEST_ID1, request);
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
JSONObject message = new JSONObject();
message.put("requestId", REQUEST_ID2);
mMessageHandler.onMessageReceived(NAMESPACE1, message.toString());
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
verify(mMessageHandler).onAppMessage(
eq(message.toString()), eq(NAMESPACE1), (RequestRecord) isNull());
}
@Test
@Feature({"MediaRouter"})
public void testOnMessageReceivedWithoutRequestId() throws JSONException {
doNothing().when(mMessageHandler).onAppMessage(
anyString(), anyString(), any(RequestRecord.class));
assertEquals(mMessageHandler.getRequestsForTest().size(), 0);
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.getRequestsForTest().append(
REQUEST_ID1, request);
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
JSONObject message = new JSONObject();
mMessageHandler.onMessageReceived(NAMESPACE1, message.toString());
assertEquals(mMessageHandler.getRequestsForTest().size(), 1);
verify(mMessageHandler).onAppMessage(
eq(message.toString()), eq(NAMESPACE1), (RequestRecord) isNull());
}
@Test
@Feature({"MediaRouter"})
public void testOnMessageReceivedOfMediaNamespace() throws JSONException {
doNothing().when(mMessageHandler).onMediaMessage(anyString(), any(RequestRecord.class));
mMessageHandler.onMessageReceived(MEDIA_NAMESPACE, "anymessage");
verify(mMessageHandler).onMediaMessage(eq("anymessage"), (RequestRecord) isNull());
}
@Test
@Feature({"MediaRouter"})
public void testOnMediaMessageOfMediaStatusTypeWithRequestRecord() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
doReturn(true).when(mMessageHandler).isMediaStatusMessage(anyString());
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.onMediaMessage("anymessage", request);
verify(mMessageHandler, never()).sendClientMessageTo(
eq(CLIENT_ID1), eq("v2_message"), eq("anymessage"), eq(INVALID_SEQUENCE_NUMBER));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID2), eq("v2_message"), eq("anymessage"), eq(INVALID_SEQUENCE_NUMBER));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("v2_message"), eq("anymessage"), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testOnMediaMessageOfMediaStatusTypeWithNullRequestRecord() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
doReturn(true).when(mMessageHandler).isMediaStatusMessage(anyString());
mMessageHandler.onMediaMessage("anymessage", null);
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("v2_message"), eq("anymessage"), eq(INVALID_SEQUENCE_NUMBER));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID2), eq("v2_message"), eq("anymessage"), eq(INVALID_SEQUENCE_NUMBER));
}
@Test
@Feature({"MediaRouter"})
public void testOnMediaMessageOfNonMediaStatusTypeWithRequestRecord() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
doReturn(false).when(mMessageHandler).isMediaStatusMessage(anyString());
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.onMediaMessage("anymessage", request);
verify(mMessageHandler, never()).sendClientMessageTo(
anyString(), anyString(), anyString(), eq(INVALID_SEQUENCE_NUMBER));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("v2_message"), eq("anymessage"), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testOnMediaMessageOfNonMediaStatusTypeWithNullRequestRecord() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
doReturn(false).when(mMessageHandler).isMediaStatusMessage(anyString());
mMessageHandler.onMediaMessage("anymessage", null);
verify(mMessageHandler, never()).sendClientMessageTo(
anyString(), anyString(), anyString(), eq(INVALID_SEQUENCE_NUMBER));
verify(mMessageHandler, never()).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
}
@Test
@Feature({"MediaRouter"})
public void testOnAppMessageWithRequestRecord() throws JSONException {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
RequestRecord request = new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1);
mMessageHandler.onAppMessage("anyMessage", NAMESPACE1, request);
JSONObject expected = new JSONObject();
expected.put("sessionId", SESSION_ID);
expected.put("namespaceName", NAMESPACE1);
expected.put("message", "anyMessage");
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("app_message"),
argThat(new JSONStringLike(expected)), eq(SEQUENCE_NUMBER1));
verify(mMessageHandler, never()).broadcastClientMessage(anyString(), anyString());
}
@Test
@Feature({"MediaRouter"})
public void testOnAppMessageWithNullRequestRecord() throws JSONException {
doNothing().when(mMessageHandler).broadcastClientMessage(anyString(), anyString());
mMessageHandler.onAppMessage("anyMessage", NAMESPACE1, null);
JSONObject expected = new JSONObject();
expected.put("sessionId", SESSION_ID);
expected.put("namespaceName", NAMESPACE1);
expected.put("message", "anyMessage");
verify(mMessageHandler, never()).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
verify(mMessageHandler).broadcastClientMessage(
eq("app_message"), argThat(new JSONStringLike(expected)));
}
@Test
@Feature({"MediaRouter"})
public void testOnApplicationStopped() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
assertEquals(0, mMessageHandler.getStopRequestsForTest().size());
mMessageHandler.getStopRequestsForTest().put(CLIENT_ID1, new ArrayDeque<Integer>());
mMessageHandler.getStopRequestsForTest().get(CLIENT_ID1).add(SEQUENCE_NUMBER1);
mMessageHandler.getStopRequestsForTest().get(CLIENT_ID1).add(SEQUENCE_NUMBER2);
assertEquals(1, mMessageHandler.getStopRequestsForTest().size());
assertEquals(2, mMessageHandler.getStopRequestsForTest().get(CLIENT_ID1).size());
mMessageHandler.onApplicationStopped();
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("remove_session"), eq(SESSION_ID), eq(SEQUENCE_NUMBER1));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("remove_session"), eq(SESSION_ID), eq(SEQUENCE_NUMBER2));
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID2), eq("remove_session"), eq(SESSION_ID), eq(INVALID_SEQUENCE_NUMBER));
}
@Test
@Feature({"MediaRouter"})
public void testOnVolumeChanged() {
doNothing().when(mMessageHandler).onVolumeChanged(anyString(), anyInt());
assertEquals(0, mMessageHandler.getVolumeRequestsForTest().size());
mMessageHandler.getVolumeRequestsForTest()
.add(new RequestRecord(CLIENT_ID1, SEQUENCE_NUMBER1));
assertEquals(1, mMessageHandler.getVolumeRequestsForTest().size());
mMessageHandler.onVolumeChanged();
verify(mMessageHandler).onVolumeChanged(CLIENT_ID1, SEQUENCE_NUMBER1);
assertEquals(0, mMessageHandler.getVolumeRequestsForTest().size());
}
@Test
@Feature({"MediaRouter"})
public void testOnVolumeChangedWithEmptyVolumeRequests() {
mMessageHandler.onVolumeChanged();
verify(mMessageHandler, never()).onVolumeChanged(eq(CLIENT_ID1), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testOnVolumeChangedForClient() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
mMessageHandler.onVolumeChanged(CLIENT_ID1, SEQUENCE_NUMBER1);
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("v2_message"), (String) isNull(), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testOnAppMessageSent() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
mMessageHandler.onAppMessageSent(CLIENT_ID1, SEQUENCE_NUMBER1);
verify(mMessageHandler).sendClientMessageTo(
eq(CLIENT_ID1), eq("app_message"), (String) isNull(), eq(SEQUENCE_NUMBER1));
}
@Test
@Feature({"MediaRouter"})
public void testSendClientMessageTo() throws JSONException {
String message = "discarded_message1";
doReturn(message).when(mMessageHandler)
.buildInternalMessage(anyString(), anyString(), anyString(), anyInt());
mMessageHandler.sendClientMessageTo(
CLIENT_ID1, "anytype", "discarded_message2", SEQUENCE_NUMBER1);
verify(mRouteProvider).onMessage(
eq(CLIENT_ID1), eq(message));
}
@Test
@Feature({"MediaRouter"})
public void testBroadcastClientMessage() {
doNothing().when(mMessageHandler).sendClientMessageTo(
anyString(), anyString(), anyString(), anyInt());
mMessageHandler.broadcastClientMessage("anytype", "anymessage");
for (String clientId : mRouteProvider.getClients()) {
verify(mMessageHandler).sendClientMessageTo(
eq(clientId), eq("anytype"), eq("anymessage"), eq(INVALID_SEQUENCE_NUMBER));
}
}
@Test
@Feature({"MediaRouter"})
public void testBuildInternalMessageWithNullMessage() throws JSONException {
String message = mMessageHandler.buildInternalMessage(
"anytype", null, CLIENT_ID1, SEQUENCE_NUMBER1);
JSONObject expected = new JSONObject();
expected.put("type", "anytype");
expected.put("sequenceNumber", SEQUENCE_NUMBER1);
expected.put("timeoutMillis", 0);
expected.put("clientId", CLIENT_ID1);
expected.put("message", null);
assertTrue("\nexpected: " + expected.toString() + ",\n actual: " + message.toString(),
new JSONObjectLike(expected).matches(new JSONObject(message)));
}
@Test
@Feature({"MediaRouter"})
public void testBuildInternalMessageOfRemoveSessionType() throws JSONException {
String message = mMessageHandler.buildInternalMessage(
"remove_session", SESSION_ID, CLIENT_ID1, SEQUENCE_NUMBER1);
JSONObject expected = new JSONObject();
expected.put("type", "remove_session");
expected.put("sequenceNumber", SEQUENCE_NUMBER1);
expected.put("timeoutMillis", 0);
expected.put("clientId", CLIENT_ID1);
expected.put("message", SESSION_ID);
assertTrue("\nexpected: " + expected.toString() + ",\n actual: " + message.toString(),
new JSONObjectLike(expected).matches(new JSONObject(message)));
}
@Test
@Feature({"MediaRouter"})
public void testBuildInternalMessageOfDisconnectSessionType() throws JSONException {
String message = mMessageHandler.buildInternalMessage(
"disconnect_session", SESSION_ID, CLIENT_ID1, SEQUENCE_NUMBER1);
JSONObject expected = new JSONObject();
expected.put("type", "disconnect_session");
expected.put("sequenceNumber", SEQUENCE_NUMBER1);
expected.put("timeoutMillis", 0);
expected.put("clientId", CLIENT_ID1);
expected.put("message", SESSION_ID);
assertTrue("\nexpected: " + expected.toString() + ",\n actual: " + message.toString(),
new JSONObjectLike(expected).matches(new JSONObject(message)));
}
@Test
@Feature({"MediaRouter"})
public void testBuildInternalMessageWithInnerMessage() throws JSONException {
JSONObject innerMessage = buildSessionMessage(SESSION_ID);
String message = mMessageHandler.buildInternalMessage(
"anytype", innerMessage.toString(), CLIENT_ID1, SEQUENCE_NUMBER1);
JSONObject expected = new JSONObject();
expected.put("type", "anytype");
expected.put("sequenceNumber", SEQUENCE_NUMBER1);
expected.put("timeoutMillis", 0);
expected.put("clientId", CLIENT_ID1);
expected.put("message", innerMessage);
assertTrue("\nexpected: " + expected.toString() + ",\n actual: " + message.toString(),
new JSONObjectLike(expected).matches(new JSONObject(message)));
}
JSONObject buildCastV2Message(String clientId, JSONObject innerMessage) throws JSONException {
JSONObject message = new JSONObject();
message.put("type", "v2_message");
message.put("message", innerMessage);
message.put("sequenceNumber", SEQUENCE_NUMBER1);
message.put("timeoutMillis", 0);
message.put("clientId", clientId);
return message;
}
JSONObject buildAppMessage(String clientId, String namespace, Object actualMessage)
throws JSONException {
JSONObject innerMessage = new JSONObject();
innerMessage.put("sessionId", mSession.getSessionId());
innerMessage.put("namespaceName", namespace);
innerMessage.put("message", actualMessage);
JSONObject message = new JSONObject();
message.put("type", "app_message");
message.put("message", innerMessage);
message.put("sequenceNumber", SEQUENCE_NUMBER1);
message.put("timeoutMillis", 0);
message.put("clientId", clientId);
return message;
}
JSONObject buildActualAppMessage() throws JSONException {
JSONObject message = new JSONObject();
message.put("type", "actual app message type");
return message;
}
JSONObject buildSessionMessage(String sessionId) throws JSONException {
JSONObject message = new JSONObject();
message.put("sessionId", sessionId);
return message;
}
void expectException(CheckedRunnable r, Class exceptionClass) {
boolean caughtException = false;
try {
r.run();
} catch (Exception e) {
if (e.getClass() == exceptionClass) caughtException = true;
}
assertTrue(caughtException);
}
JSONObject buildJsonCastMessage(String message) throws JSONException {
JSONObject jsonMessage = new JSONObject();
jsonMessage.put("requestId", REQUEST_ID1);
jsonMessage.put("message", message);
return jsonMessage;
}
}