blob: 1151046993bc11f77f334ad72386b9ca31a793fd [file] [log] [blame]
// Copyright 2018 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.
#include "components/mirroring/service/receiver_response.h"
#include "base/base64.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/test/mock_callback.h"
#include "components/mirroring/service/value_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::InvokeWithoutArgs;
using ::testing::_;
namespace mirroring {
class ReceiverResponseTest : public ::testing::Test {
public:
ReceiverResponseTest() {}
~ReceiverResponseTest() override {}
private:
DISALLOW_COPY_AND_ASSIGN(ReceiverResponseTest);
};
TEST_F(ReceiverResponseTest, ParseValidJson) {
const std::string response_string = "{\"type\":\"ANSWER\",\"result\":\"ok\"}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(-1, response.session_id);
EXPECT_EQ(-1, response.sequence_number);
EXPECT_EQ(ResponseType::ANSWER, response.type);
EXPECT_EQ("ok", response.result);
EXPECT_FALSE(response.answer);
EXPECT_FALSE(response.status);
EXPECT_FALSE(response.capabilities);
EXPECT_FALSE(response.error);
EXPECT_TRUE(response.rpc.empty());
}
TEST_F(ReceiverResponseTest, ParseInvalidValueType) {
const std::string response_string =
"{\"sessionId\":123, \"seqNum\":\"one-two-three\"}";
ReceiverResponse response;
EXPECT_FALSE(response.Parse(response_string));
}
TEST_F(ReceiverResponseTest, ParseNonJsonString) {
const std::string response_string = "This is not JSON.";
ReceiverResponse response;
EXPECT_FALSE(response.Parse(response_string));
}
TEST_F(ReceiverResponseTest, ParseRealWorldAnswerMessage) {
const std::string response_string =
"{\"answer\":{\"receiverRtcpEventLog\":[0,1],\"rtpExtensions\":"
"[[\"adaptive_playout_delay\"],[\"adaptive_playout_delay\"]],"
"\"sendIndexes\":[0,1],\"ssrcs\":[40863,759293],\"udpPort\":50691,"
"\"castMode\":\"mirroring\"},\"result\":\"ok\",\"seqNum\":989031000,"
"\"type\":\"ANSWER\"}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(-1, response.session_id);
EXPECT_EQ(989031000, response.sequence_number);
EXPECT_EQ(ResponseType::ANSWER, response.type);
EXPECT_EQ("ok", response.result);
ASSERT_TRUE(response.answer);
EXPECT_EQ(50691, response.answer->udp_port);
EXPECT_EQ(std::vector<int32_t>({0, 1}), response.answer->send_indexes);
EXPECT_EQ(std::vector<int32_t>({40863, 759293}), response.answer->ssrcs);
EXPECT_TRUE(response.answer->iv.empty());
EXPECT_EQ(false, response.answer->supports_get_status);
EXPECT_EQ("mirroring", response.answer->cast_mode);
EXPECT_FALSE(response.status);
EXPECT_FALSE(response.capabilities);
EXPECT_FALSE(response.error);
}
TEST_F(ReceiverResponseTest, ParseErrorMessage) {
const std::string response_string =
"{\"sessionId\": 123,"
"\"seqNum\": 999,"
"\"type\": \"ANSWER\","
"\"result\": \"error\","
"\"error\": {"
"\"code\": 42,"
"\"description\": \"it is broke\","
"\"details\": {\"foo\": -1, \"bar\": 88}"
"}"
"}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(123, response.session_id);
EXPECT_EQ(999, response.sequence_number);
EXPECT_EQ(ResponseType::ANSWER, response.type);
EXPECT_EQ("error", response.result);
EXPECT_FALSE(response.answer);
EXPECT_FALSE(response.status);
EXPECT_FALSE(response.capabilities);
ASSERT_TRUE(response.error);
EXPECT_EQ(42, response.error->code);
EXPECT_EQ("it is broke", response.error->description);
std::unique_ptr<base::Value> parsed_details =
base::JSONReader::ReadDeprecated(response.error->details);
ASSERT_TRUE(parsed_details && parsed_details->is_dict());
EXPECT_EQ(2u, parsed_details->DictSize());
int fool_value = 0;
EXPECT_TRUE(GetInt(*parsed_details, "foo", &fool_value));
EXPECT_EQ(-1, fool_value);
int bar_value = 0;
EXPECT_TRUE(GetInt(*parsed_details, "bar", &bar_value));
EXPECT_EQ(88, bar_value);
}
TEST_F(ReceiverResponseTest, ParseStatusMessage) {
const std::string response_string =
"{\"seqNum\": 777,"
"\"type\": \"STATUS_RESPONSE\","
"\"result\": \"ok\","
"\"status\": {"
"\"wifiSnr\": 36.7,"
"\"wifiSpeed\": [1234, 5678, 3000, 3001],"
"\"wifiFcsError\": [12, 13, 12, 12]}" // This will be ignored.
"}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(777, response.sequence_number);
EXPECT_EQ(ResponseType::STATUS_RESPONSE, response.type);
EXPECT_EQ("ok", response.result);
EXPECT_FALSE(response.error);
EXPECT_FALSE(response.answer);
ASSERT_TRUE(response.status);
EXPECT_EQ(36.7, response.status->wifi_snr);
const std::vector<int32_t> expect_speed({1234, 5678, 3000, 3001});
EXPECT_EQ(expect_speed, response.status->wifi_speed);
EXPECT_FALSE(response.capabilities);
}
TEST_F(ReceiverResponseTest, ParseCapabilityMessage) {
const std::string response_string =
"{\"sessionId\": 999888777,"
"\"seqNum\": 5551212,"
"\"type\": \"CAPABILITIES_RESPONSE\","
"\"result\": \"ok\","
"\"capabilities\": {"
"\"mediaCaps\": [\"audio\", \"video\", \"vp9\"],"
"\"keySystems\": ["
"{"
"\"keySystemName\": \"com.w3c.clearkey\""
"},"
"{"
"\"keySystemName\": \"com.widevine.alpha\","
"\"initDataTypes\": [\"a\", \"b\", \"c\", \"1\", \"2\", \"3\"],"
"\"codecs\": [\"vp8\", \"h264\"],"
"\"secureCodecs\": [\"h264\", \"vp8\"],"
"\"audioRobustness\": [\"nope\"],"
"\"videoRobustness\": [\"yep\"],"
"\"persistentLicenseSessionSupport\": \"SUPPORTED\","
"\"persistentReleaseMessageSessionSupport\": \"SUPPORTED_WITH_ID\","
"\"persistentStateSupport\": \"REQUESTABLE\","
"\"distinctiveIdentifierSupport\": \"ALWAYS_ENABLED\""
"}"
"]}}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(999888777, response.session_id);
EXPECT_EQ(5551212, response.sequence_number);
EXPECT_EQ(ResponseType::CAPABILITIES_RESPONSE, response.type);
EXPECT_EQ("ok", response.result);
EXPECT_FALSE(response.error);
EXPECT_FALSE(response.answer);
EXPECT_FALSE(response.status);
ASSERT_TRUE(response.capabilities);
EXPECT_EQ(std::vector<std::string>({"audio", "video", "vp9"}),
response.capabilities->media_caps);
const ReceiverKeySystem& first_key_system =
response.capabilities->key_systems[0];
EXPECT_EQ("com.w3c.clearkey", first_key_system.name);
EXPECT_TRUE(first_key_system.init_data_types.empty());
EXPECT_TRUE(first_key_system.codecs.empty());
EXPECT_TRUE(first_key_system.secure_codecs.empty());
EXPECT_TRUE(first_key_system.audio_robustness.empty());
EXPECT_TRUE(first_key_system.video_robustness.empty());
EXPECT_TRUE(first_key_system.persistent_license_session_support.empty());
EXPECT_TRUE(
first_key_system.persistent_release_message_session_support.empty());
EXPECT_TRUE(first_key_system.persistent_state_support.empty());
EXPECT_TRUE(first_key_system.distinctive_identifier_support.empty());
const ReceiverKeySystem& second_key_system =
response.capabilities->key_systems[1];
EXPECT_EQ("com.widevine.alpha", second_key_system.name);
EXPECT_EQ(std::vector<std::string>({"a", "b", "c", "1", "2", "3"}),
second_key_system.init_data_types);
EXPECT_EQ(std::vector<std::string>({"vp8", "h264"}),
second_key_system.codecs);
EXPECT_EQ(std::vector<std::string>({"h264", "vp8"}),
second_key_system.secure_codecs);
EXPECT_EQ(std::vector<std::string>({"nope"}),
second_key_system.audio_robustness);
EXPECT_EQ(std::vector<std::string>({"yep"}),
second_key_system.video_robustness);
EXPECT_EQ("SUPPORTED", second_key_system.persistent_license_session_support);
EXPECT_EQ("SUPPORTED_WITH_ID",
second_key_system.persistent_release_message_session_support);
EXPECT_EQ("REQUESTABLE", second_key_system.persistent_state_support);
EXPECT_EQ("ALWAYS_ENABLED", second_key_system.distinctive_identifier_support);
}
TEST_F(ReceiverResponseTest, ParseRpcMessage) {
const std::string message = "Hello from the Cast Receiver!";
std::string rpc_base64;
base::Base64Encode(message, &rpc_base64);
std::string response_string =
"{\"sessionId\": 735189,"
"\"seqNum\": 6789,"
"\"type\": \"RPC\","
"\"result\": \"ok\","
"\"rpc\": \"" +
rpc_base64 + "\"}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(735189, response.session_id);
EXPECT_EQ(6789, response.sequence_number);
EXPECT_EQ("ok", response.result);
EXPECT_EQ(ResponseType::RPC, response.type);
EXPECT_EQ(message, response.rpc);
EXPECT_FALSE(response.error);
EXPECT_FALSE(response.answer);
EXPECT_FALSE(response.status);
EXPECT_FALSE(response.capabilities);
}
TEST_F(ReceiverResponseTest, ParseResponseWithNullField) {
const std::string response_string =
"{\"sessionId\":null,\"seqNum\":808907000,\"type\":\"ANSWER\","
"\"result\":\"ok\",\"rpc\":null,\"error\":null,"
"\"answer\":{\"udpPort\":51706,\"sendIndexes\":[0,1],"
"\"ssrcs\":[152818,556029],\"IV\":null,\"receiverGetStatus\":true,"
"\"castMode\":\"mirroring\"},\"status\":null,\"capabilities\":null}";
ReceiverResponse response;
ASSERT_TRUE(response.Parse(response_string));
EXPECT_EQ(808907000, response.sequence_number);
EXPECT_EQ("ok", response.result);
EXPECT_FALSE(response.error);
EXPECT_FALSE(response.status);
EXPECT_FALSE(response.capabilities);
EXPECT_TRUE(response.rpc.empty());
EXPECT_EQ(ResponseType::ANSWER, response.type);
ASSERT_TRUE(response.answer);
EXPECT_EQ(51706, response.answer->udp_port);
EXPECT_EQ(std::vector<int32_t>({0, 1}), response.answer->send_indexes);
EXPECT_EQ(std::vector<int32_t>({152818, 556029}), response.answer->ssrcs);
EXPECT_TRUE(response.answer->iv.empty());
EXPECT_EQ(true, response.answer->supports_get_status);
EXPECT_EQ("mirroring", response.answer->cast_mode);
}
} // namespace mirroring