aboutsummaryrefslogtreecommitdiff
path: root/cast/streaming/receiver_session_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'cast/streaming/receiver_session_unittest.cc')
-rw-r--r--cast/streaming/receiver_session_unittest.cc602
1 files changed, 557 insertions, 45 deletions
diff --git a/cast/streaming/receiver_session_unittest.cc b/cast/streaming/receiver_session_unittest.cc
index 1914cbd5..098695a8 100644
--- a/cast/streaming/receiver_session_unittest.cc
+++ b/cast/streaming/receiver_session_unittest.cc
@@ -15,6 +15,7 @@
#include "platform/test/fake_clock.h"
#include "platform/test/fake_task_runner.h"
#include "util/chrono_helpers.h"
+#include "util/json/json_serialization.h"
using ::testing::_;
using ::testing::InSequence;
@@ -33,7 +34,6 @@ constexpr char kValidOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": [
{
"index": 31337,
@@ -78,6 +78,26 @@ constexpr char kValidOfferMessage[] = R"({
]
},
{
+ "index": 31339,
+ "type": "video_source",
+ "codecName": "hevc",
+ "codecParameter": "hev1.1.6.L150.B0",
+ "rtpProfile": "cast",
+ "rtpPayloadType": 127,
+ "ssrc": 19088746,
+ "maxFrameRate": "120",
+ "timeBase": "1/90000",
+ "maxBitRate": 5000000,
+ "aesKey": "040d756791711fd3adb939066e6d8690",
+ "aesIvMask": "9ff0f022a959150e70a2d05a6c184aed",
+ "resolutions": [
+ {
+ "width": 1920,
+ "height": 1080
+ }
+ ]
+ },
+ {
"index": 1337,
"type": "audio_source",
"codecName": "opus",
@@ -94,12 +114,53 @@ constexpr char kValidOfferMessage[] = R"({
}
})";
+constexpr char kValidRemotingOfferMessage[] = R"({
+ "type": "OFFER",
+ "seqNum": 419,
+ "offer": {
+ "castMode": "remoting",
+ "supportedStreams": [
+ {
+ "index": 31339,
+ "type": "video_source",
+ "codecName": "REMOTE_VIDEO",
+ "rtpProfile": "cast",
+ "rtpPayloadType": 127,
+ "ssrc": 19088745,
+ "maxFrameRate": "60000/1000",
+ "timeBase": "1/90000",
+ "maxBitRate": 5432101,
+ "aesKey": "040d756791711fd3adb939066e6d8690",
+ "aesIvMask": "9ff0f022a959150e70a2d05a6c184aed",
+ "resolutions": [
+ {
+ "width": 1920,
+ "height":1080
+ }
+ ]
+ },
+ {
+ "index": 31340,
+ "type": "audio_source",
+ "codecName": "REMOTE_AUDIO",
+ "rtpProfile": "cast",
+ "rtpPayloadType": 97,
+ "ssrc": 19088747,
+ "bitRate": 125000,
+ "timeBase": "1/48000",
+ "channels": 2,
+ "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
+ "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
+ }
+ ]
+ }
+})";
+
constexpr char kNoAudioOfferMessage[] = R"({
"type": "OFFER",
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": [
{
"index": 31338,
@@ -131,7 +192,6 @@ constexpr char kInvalidCodecOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": [
{
"index": 31338,
@@ -163,7 +223,6 @@ constexpr char kNoVideoOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": [
{
"index": 1337,
@@ -187,7 +246,6 @@ constexpr char kNoAudioOrVideoOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": []
}
})";
@@ -197,7 +255,6 @@ constexpr char kInvalidJsonOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": [
}
})";
@@ -211,7 +268,6 @@ constexpr char kMissingSeqNumOfferMessage[] = R"({
"type": "OFFER",
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": []
}
})";
@@ -221,7 +277,6 @@ constexpr char kValidJsonInvalidFormatOfferMessage[] = R"({
"seqNum": 1337,
"offer": {
"castMode": "mirroring",
- "receiverGetStatus": true,
"supportedStreams": "anything"
}
})";
@@ -246,17 +301,36 @@ constexpr char kInvalidTypeMessage[] = R"({
"seqNum": 1337
})";
+constexpr char kGetCapabilitiesMessage[] = R"({
+ "seqNum": 820263770,
+ "type": "GET_CAPABILITIES"
+})";
+
+constexpr char kRpcMessage[] = R"({
+ "rpc" : "CGQQnBiCGQgSAggMGgIIBg==",
+ "seqNum" : 2,
+ "type" : "RPC"
+})";
+
class FakeClient : public ReceiverSession::Client {
public:
MOCK_METHOD(void,
- OnMirroringNegotiated,
+ OnNegotiated,
(const ReceiverSession*, ReceiverSession::ConfiguredReceivers),
(override));
MOCK_METHOD(void,
+ OnRemotingNegotiated,
+ (const ReceiverSession*, ReceiverSession::RemotingNegotiation),
+ (override));
+ MOCK_METHOD(void,
OnReceiversDestroying,
(const ReceiverSession*, ReceiversDestroyingReason),
(override));
MOCK_METHOD(void, OnError, (const ReceiverSession*, Error error), (override));
+ MOCK_METHOD(bool,
+ SupportsCodecParameter,
+ (const std::string& parameter),
+ (override));
};
void ExpectIsErrorAnswerMessage(const ErrorOr<Json::Value>& message_or_error) {
@@ -288,12 +362,17 @@ class ReceiverSessionTest : public ::testing::Test {
return environment_;
}
- void SetUp() {
+ void SetUp() { SetUpWithPreferences(ReceiverSession::Preferences{}); }
+
+ // Since preferences are constant throughout the life of a session,
+ // changing them requires configuring a new session.
+ void SetUpWithPreferences(ReceiverSession::Preferences preferences) {
+ session_.reset();
message_port_ = std::make_unique<SimpleMessagePort>("sender-12345");
environment_ = MakeEnvironment();
- session_ = std::make_unique<ReceiverSession>(
- &client_, environment_.get(), message_port_.get(),
- ReceiverSession::Preferences{});
+ session_ = std::make_unique<ReceiverSession>(&client_, environment_.get(),
+ message_port_.get(),
+ std::move(preferences));
}
protected:
@@ -315,7 +394,7 @@ class ReceiverSessionTest : public ::testing::Test {
TEST_F(ReceiverSessionTest, CanNegotiateWithDefaultPreferences) {
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _))
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _))
.WillOnce([](const ReceiverSession* session_,
ReceiverSession::ConfiguredReceivers cr) {
EXPECT_TRUE(cr.audio_receiver);
@@ -364,9 +443,6 @@ TEST_F(ReceiverSessionTest, CanNegotiateWithDefaultPreferences) {
EXPECT_LT(0, answer_body["udpPort"].asInt());
EXPECT_GT(65535, answer_body["udpPort"].asInt());
- // Get status should always be false, as we have no plans to implement it.
- EXPECT_EQ(false, answer_body["receiverGetStatus"].asBool());
-
// Constraints and display should not be present with no preferences.
EXPECT_TRUE(answer_body["constraints"].isNull());
EXPECT_TRUE(answer_body["display"].isNull());
@@ -378,7 +454,7 @@ TEST_F(ReceiverSessionTest, CanNegotiateWithCustomCodecPreferences) {
ReceiverSession::Preferences{{VideoCodec::kVp9}, {AudioCodec::kOpus}});
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(&session, _))
+ EXPECT_CALL(client_, OnNegotiated(&session, _))
.WillOnce([](const ReceiverSession* session_,
ReceiverSession::ConfiguredReceivers cr) {
EXPECT_TRUE(cr.audio_receiver);
@@ -400,28 +476,88 @@ TEST_F(ReceiverSessionTest, CanNegotiateWithCustomCodecPreferences) {
message_port_->ReceiveMessage(kValidOfferMessage);
}
-TEST_F(ReceiverSessionTest, CanNegotiateWithCustomConstraints) {
- auto constraints = std::make_unique<Constraints>(Constraints{
- AudioConstraints{48001, 2, 32001, 32002, milliseconds(3001)},
- VideoConstraints{3.14159,
- absl::optional<Dimensions>(
- Dimensions{320, 240, SimpleFraction{24, 1}}),
- Dimensions{1920, 1080, SimpleFraction{144, 1}}, 300000,
- 90000000, milliseconds(1000)}});
+TEST_F(ReceiverSessionTest, RejectsStreamWithUnsupportedCodecParameter) {
+ ReceiverSession::Preferences preferences({VideoCodec::kHevc},
+ {AudioCodec::kOpus});
+ EXPECT_CALL(client_, SupportsCodecParameter(_)).WillRepeatedly(Return(false));
+ ReceiverSession session(&client_, environment_.get(), message_port_.get(),
+ preferences);
+ InSequence s;
+ EXPECT_CALL(client_, OnNegotiated(&session, _))
+ .WillOnce([](const ReceiverSession* session_,
+ ReceiverSession::ConfiguredReceivers cr) {
+ EXPECT_FALSE(cr.video_receiver);
+ });
+ EXPECT_CALL(client_, OnReceiversDestroying(
+ &session, ReceiverSession::Client::kEndOfSession));
+ message_port_->ReceiveMessage(kValidOfferMessage);
+}
+
+TEST_F(ReceiverSessionTest, AcceptsStreamWithNoCodecParameter) {
+ ReceiverSession::Preferences preferences(
+ {VideoCodec::kHevc, VideoCodec::kVp9}, {AudioCodec::kOpus});
+ EXPECT_CALL(client_, SupportsCodecParameter(_)).WillRepeatedly(Return(false));
+
+ ReceiverSession session(&client_, environment_.get(), message_port_.get(),
+ std::move(preferences));
+ InSequence s;
+ EXPECT_CALL(client_, OnNegotiated(&session, _))
+ .WillOnce([](const ReceiverSession* session_,
+ ReceiverSession::ConfiguredReceivers cr) {
+ EXPECT_TRUE(cr.video_receiver);
+ EXPECT_EQ(cr.video_config.codec, VideoCodec::kVp9);
+ });
+ EXPECT_CALL(client_, OnReceiversDestroying(
+ &session, ReceiverSession::Client::kEndOfSession));
+ message_port_->ReceiveMessage(kValidOfferMessage);
+}
+
+TEST_F(ReceiverSessionTest, AcceptsStreamWithMatchingParameter) {
+ ReceiverSession::Preferences preferences({VideoCodec::kHevc},
+ {AudioCodec::kOpus});
+ EXPECT_CALL(client_, SupportsCodecParameter(_))
+ .WillRepeatedly(
+ [](const std::string& param) { return param == "hev1.1.6.L150.B0"; });
+
+ ReceiverSession session(&client_, environment_.get(), message_port_.get(),
+ std::move(preferences));
+ InSequence s;
+ EXPECT_CALL(client_, OnNegotiated(&session, _))
+ .WillOnce([](const ReceiverSession* session_,
+ ReceiverSession::ConfiguredReceivers cr) {
+ EXPECT_TRUE(cr.video_receiver);
+ EXPECT_EQ(cr.video_config.codec, VideoCodec::kHevc);
+ });
+ EXPECT_CALL(client_, OnReceiversDestroying(
+ &session, ReceiverSession::Client::kEndOfSession));
+ message_port_->ReceiveMessage(kValidOfferMessage);
+}
- auto display = std::make_unique<DisplayDescription>(DisplayDescription{
- absl::optional<Dimensions>(Dimensions{640, 480, SimpleFraction{60, 1}}),
- absl::optional<AspectRatio>(AspectRatio{16, 9}),
- absl::optional<AspectRatioConstraint>(AspectRatioConstraint::kFixed)});
+TEST_F(ReceiverSessionTest, CanNegotiateWithLimits) {
+ std::vector<ReceiverSession::AudioLimits> audio_limits = {
+ {false, AudioCodec::kOpus, 48001, 2, 32001, 32002, milliseconds(3001)}};
+ std::vector<ReceiverSession::VideoLimits> video_limits = {
+ {true,
+ VideoCodec::kVp9,
+ 62208000,
+ {1920, 1080, {144, 1}},
+ 300000,
+ 90000000,
+ milliseconds(1000)}};
+
+ auto display =
+ std::make_unique<ReceiverSession::Display>(ReceiverSession::Display{
+ {640, 480, {60, 1}}, false /* can scale content */});
ReceiverSession session(&client_, environment_.get(), message_port_.get(),
ReceiverSession::Preferences{{VideoCodec::kVp9},
{AudioCodec::kOpus},
- std::move(constraints),
+ std::move(audio_limits),
+ std::move(video_limits),
std::move(display)});
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(&session, _));
+ EXPECT_CALL(client_, OnNegotiated(&session, _));
EXPECT_CALL(client_, OnReceiversDestroying(
&session, ReceiverSession::Client::kEndOfSession));
message_port_->ReceiveMessage(kValidOfferMessage);
@@ -434,14 +570,13 @@ TEST_F(ReceiverSessionTest, CanNegotiateWithCustomConstraints) {
const Json::Value answer = std::move(message_body.value());
const Json::Value& answer_body = answer["answer"];
- ASSERT_TRUE(answer_body.isObject());
+ ASSERT_TRUE(answer_body.isObject()) << messages[0];
// Constraints and display should be valid with valid preferences.
ASSERT_FALSE(answer_body["constraints"].isNull());
ASSERT_FALSE(answer_body["display"].isNull());
const Json::Value& display_json = answer_body["display"];
- EXPECT_EQ("16:9", display_json["aspectRatio"].asString());
EXPECT_EQ("60", display_json["dimensions"]["frameRate"].asString());
EXPECT_EQ(640, display_json["dimensions"]["width"].asInt());
EXPECT_EQ(480, display_json["dimensions"]["height"].asInt());
@@ -465,16 +600,12 @@ TEST_F(ReceiverSessionTest, CanNegotiateWithCustomConstraints) {
EXPECT_EQ("144", video["maxDimensions"]["frameRate"].asString());
EXPECT_EQ(1920, video["maxDimensions"]["width"].asInt());
EXPECT_EQ(1080, video["maxDimensions"]["height"].asInt());
- EXPECT_DOUBLE_EQ(3.14159, video["maxPixelsPerSecond"].asDouble());
EXPECT_EQ(300000, video["minBitRate"].asInt());
- EXPECT_EQ("24", video["minDimensions"]["frameRate"].asString());
- EXPECT_EQ(320, video["minDimensions"]["width"].asInt());
- EXPECT_EQ(240, video["minDimensions"]["height"].asInt());
}
TEST_F(ReceiverSessionTest, HandlesNoValidAudioStream) {
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _));
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _));
EXPECT_CALL(client_,
OnReceiversDestroying(session_.get(),
ReceiverSession::Client::kEndOfSession));
@@ -511,7 +642,7 @@ TEST_F(ReceiverSessionTest, HandlesInvalidCodec) {
TEST_F(ReceiverSessionTest, HandlesNoValidVideoStream) {
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _));
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _));
EXPECT_CALL(client_,
OnReceiversDestroying(session_.get(),
ReceiverSession::Client::kEndOfSession));
@@ -533,8 +664,7 @@ TEST_F(ReceiverSessionTest, HandlesNoValidVideoStream) {
}
TEST_F(ReceiverSessionTest, HandlesNoValidStreams) {
- // We shouldn't call OnMirroringNegotiated if we failed to negotiate any
- // streams.
+ // We shouldn't call OnNegotiated if we failed to negotiate any streams.
message_port_->ReceiveMessage(kNoAudioOrVideoOfferMessage);
AssertGotAnErrorAnswerResponse();
}
@@ -596,11 +726,11 @@ TEST_F(ReceiverSessionTest, DoesNotCrashOnMessagePortError) {
TEST_F(ReceiverSessionTest, NotifiesReceiverDestruction) {
InSequence s;
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _));
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _));
EXPECT_CALL(client_,
OnReceiversDestroying(session_.get(),
ReceiverSession::Client::kRenegotiated));
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _));
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _));
EXPECT_CALL(client_,
OnReceiversDestroying(session_.get(),
ReceiverSession::Client::kEndOfSession));
@@ -638,7 +768,7 @@ TEST_F(ReceiverSessionTest, DelaysAnswerUntilEnvironmentIsReady) {
// state() will not be called again--we just need to get the bind event.
EXPECT_CALL(*environment_, GetBoundLocalEndpoint())
.WillOnce(Return(IPEndpoint{{10, 0, 0, 2}, 4567}));
- EXPECT_CALL(client_, OnMirroringNegotiated(session_.get(), _));
+ EXPECT_CALL(client_, OnNegotiated(session_.get(), _));
EXPECT_CALL(client_,
OnReceiversDestroying(session_.get(),
ReceiverSession::Client::kEndOfSession));
@@ -691,5 +821,387 @@ TEST_F(ReceiverSessionTest, ReturnsErrorAnswerIfEnvironmentIsInvalidated) {
EXPECT_EQ("error", message_body.value()["result"].asString());
}
+TEST_F(ReceiverSessionTest, ReturnsErrorCapabilitiesIfRemotingDisabled) {
+ message_port_->ReceiveMessage(kGetCapabilitiesMessage);
+ const auto& messages = message_port_->posted_messages();
+ ASSERT_EQ(1u, messages.size());
+
+ // We should have an error response.
+ auto message_body = json::Parse(messages[0]);
+ EXPECT_TRUE(message_body.is_value());
+ EXPECT_EQ("CAPABILITIES_RESPONSE", message_body.value()["type"].asString());
+ EXPECT_EQ("error", message_body.value()["result"].asString());
+}
+
+TEST_F(ReceiverSessionTest, ReturnsCapabilitiesWithRemotingDefaults) {
+ ReceiverSession::Preferences preferences;
+ preferences.remoting =
+ std::make_unique<ReceiverSession::RemotingPreferences>();
+
+ SetUpWithPreferences(std::move(preferences));
+ message_port_->ReceiveMessage(kGetCapabilitiesMessage);
+ const auto& messages = message_port_->posted_messages();
+ ASSERT_EQ(1u, messages.size());
+
+ // We should have an error response.
+ auto message_body = json::Parse(messages[0]);
+ EXPECT_TRUE(message_body.is_value());
+ EXPECT_EQ("CAPABILITIES_RESPONSE", message_body.value()["type"].asString());
+ EXPECT_EQ("ok", message_body.value()["result"].asString());
+ const ReceiverCapability response =
+ ReceiverCapability::Parse(message_body.value()["capabilities"]).value();
+
+ EXPECT_THAT(
+ response.media_capabilities,
+ testing::ElementsAre(MediaCapability::kOpus, MediaCapability::kAac,
+ MediaCapability::kVp8, MediaCapability::kH264));
+}
+
+TEST_F(ReceiverSessionTest, ReturnsCapabilitiesWithRemotingPreferences) {
+ ReceiverSession::Preferences preferences;
+ preferences.video_codecs = {VideoCodec::kH264};
+ preferences.remoting =
+ std::make_unique<ReceiverSession::RemotingPreferences>();
+ preferences.remoting->supports_chrome_audio_codecs = true;
+ preferences.remoting->supports_4k = true;
+
+ SetUpWithPreferences(std::move(preferences));
+ message_port_->ReceiveMessage(kGetCapabilitiesMessage);
+ const auto& messages = message_port_->posted_messages();
+ ASSERT_EQ(1u, messages.size());
+
+ // We should have an error response.
+ auto message_body = json::Parse(messages[0]);
+ EXPECT_TRUE(message_body.is_value());
+ EXPECT_EQ("CAPABILITIES_RESPONSE", message_body.value()["type"].asString());
+ EXPECT_EQ("ok", message_body.value()["result"].asString());
+ const ReceiverCapability response =
+ ReceiverCapability::Parse(message_body.value()["capabilities"]).value();
+
+ EXPECT_THAT(
+ response.media_capabilities,
+ testing::ElementsAre(MediaCapability::kOpus, MediaCapability::kAac,
+ MediaCapability::kH264, MediaCapability::kAudio,
+ MediaCapability::k4k));
+}
+
+TEST_F(ReceiverSessionTest, CanNegotiateRemoting) {
+ ReceiverSession::Preferences preferences;
+ preferences.remoting =
+ std::make_unique<ReceiverSession::RemotingPreferences>();
+ preferences.remoting->supports_chrome_audio_codecs = true;
+ preferences.remoting->supports_4k = true;
+ SetUpWithPreferences(std::move(preferences));
+
+ InSequence s;
+ EXPECT_CALL(client_, OnRemotingNegotiated(session_.get(), _))
+ .WillOnce([](const ReceiverSession* session_,
+ ReceiverSession::RemotingNegotiation negotiation) {
+ const auto& cr = negotiation.receivers;
+ EXPECT_TRUE(cr.audio_receiver);
+ EXPECT_EQ(cr.audio_receiver->config().sender_ssrc, 19088747u);
+ EXPECT_EQ(cr.audio_receiver->config().receiver_ssrc, 19088748u);
+ EXPECT_EQ(cr.audio_receiver->config().channels, 2);
+ EXPECT_EQ(cr.audio_receiver->config().rtp_timebase, 48000);
+ EXPECT_EQ(cr.audio_config.codec, AudioCodec::kNotSpecified);
+
+ EXPECT_TRUE(cr.video_receiver);
+ EXPECT_EQ(cr.video_receiver->config().sender_ssrc, 19088745u);
+ EXPECT_EQ(cr.video_receiver->config().receiver_ssrc, 19088746u);
+ EXPECT_EQ(cr.video_receiver->config().channels, 1);
+ EXPECT_EQ(cr.video_receiver->config().rtp_timebase, 90000);
+ EXPECT_EQ(cr.video_config.codec, VideoCodec::kNotSpecified);
+ });
+ EXPECT_CALL(client_,
+ OnReceiversDestroying(session_.get(),
+ ReceiverSession::Client::kEndOfSession));
+
+ message_port_->ReceiveMessage(kValidRemotingOfferMessage);
+}
+
+TEST_F(ReceiverSessionTest, HandlesRpcMessage) {
+ ReceiverSession::Preferences preferences;
+ preferences.remoting =
+ std::make_unique<ReceiverSession::RemotingPreferences>();
+ preferences.remoting->supports_chrome_audio_codecs = true;
+ preferences.remoting->supports_4k = true;
+ SetUpWithPreferences(std::move(preferences));
+
+ message_port_->ReceiveMessage(kRpcMessage);
+ const auto& messages = message_port_->posted_messages();
+ // Nothing should happen yet, the session doesn't have a messenger.
+ ASSERT_EQ(0u, messages.size());
+
+ // We don't need to fully test that the subscription model on the RpcMessenger
+ // works, but we do want to test that the ReceiverSession has properly wired
+ // the RpcMessenger up to the backing SessionMessenger and can properly
+ // handle received RPC messages.
+ InSequence s;
+ bool received_initialize_message = false;
+ EXPECT_CALL(client_, OnRemotingNegotiated(session_.get(), _))
+ .WillOnce([this, &received_initialize_message](
+ const ReceiverSession* session_,
+ ReceiverSession::RemotingNegotiation negotiation) mutable {
+ negotiation.messenger->RegisterMessageReceiverCallback(
+ 100, [&received_initialize_message](
+ std::unique_ptr<RpcMessage> message) mutable {
+ ASSERT_EQ(100, message->handle());
+ ASSERT_EQ(RpcMessage::RPC_DS_INITIALIZE_CALLBACK,
+ message->proc());
+ ASSERT_EQ(0, message->integer_value());
+ received_initialize_message = true;
+ });
+
+ message_port_->ReceiveMessage(kRpcMessage);
+ });
+ EXPECT_CALL(client_,
+ OnReceiversDestroying(session_.get(),
+ ReceiverSession::Client::kEndOfSession));
+
+ message_port_->ReceiveMessage(kValidRemotingOfferMessage);
+ ASSERT_TRUE(received_initialize_message);
+}
+
+TEST_F(ReceiverSessionTest, VideoLimitsIsSupersetOf) {
+ ReceiverSession::VideoLimits first{};
+ ReceiverSession::VideoLimits second = first;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.max_pixels_per_second += 1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.max_pixels_per_second = second.max_pixels_per_second;
+
+ first.max_dimensions = {1921, 1090, {kDefaultFrameRate, 1}};
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+
+ second.max_dimensions = {1921, 1090, {kDefaultFrameRate + 1, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ second.max_dimensions = {2000, 1000, {kDefaultFrameRate, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.max_dimensions = first.max_dimensions;
+
+ first.min_bit_rate += 1;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.min_bit_rate = second.min_bit_rate;
+
+ first.max_bit_rate += 1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.max_bit_rate = second.max_bit_rate;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.applies_to_all_codecs = true;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.applies_to_all_codecs = true;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.codec = VideoCodec::kVp8;
+ second.codec = VideoCodec::kVp9;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.applies_to_all_codecs = false;
+ second.applies_to_all_codecs = false;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+}
+
+TEST_F(ReceiverSessionTest, AudioLimitsIsSupersetOf) {
+ ReceiverSession::AudioLimits first{};
+ ReceiverSession::AudioLimits second = first;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.max_sample_rate += 1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.max_sample_rate = second.max_sample_rate;
+
+ first.max_channels += 1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.max_channels = second.max_channels;
+
+ first.min_bit_rate += 1;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.min_bit_rate = second.min_bit_rate;
+
+ first.max_bit_rate += 1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.max_bit_rate = second.max_bit_rate;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.applies_to_all_codecs = true;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.applies_to_all_codecs = true;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.codec = AudioCodec::kOpus;
+ second.codec = AudioCodec::kAac;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.applies_to_all_codecs = false;
+ second.applies_to_all_codecs = false;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+}
+
+TEST_F(ReceiverSessionTest, DisplayIsSupersetOf) {
+ ReceiverSession::Display first;
+ ReceiverSession::Display second = first;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.dimensions = {1921, 1090, {kDefaultFrameRate, 1}};
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+
+ second.dimensions = {1921, 1090, {kDefaultFrameRate + 1, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ second.dimensions = {2000, 1000, {kDefaultFrameRate, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.dimensions = first.dimensions;
+
+ first.can_scale_content = true;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+}
+
+TEST_F(ReceiverSessionTest, RemotingPreferencesIsSupersetOf) {
+ ReceiverSession::RemotingPreferences first;
+ ReceiverSession::RemotingPreferences second = first;
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ first.supports_chrome_audio_codecs = true;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+
+ second.supports_4k = true;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+
+ second.supports_chrome_audio_codecs = true;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+}
+
+TEST_F(ReceiverSessionTest, PreferencesIsSupersetOf) {
+ ReceiverSession::Preferences first;
+ ReceiverSession::Preferences second(first);
+
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+
+ // Modified |display_description|.
+ first.display_description = std::make_unique<ReceiverSession::Display>();
+ first.display_description->dimensions = {1920, 1080, {kDefaultFrameRate, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second = first;
+
+ first.display_description->dimensions = {192, 1080, {kDefaultFrameRate, 1}};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ second = first;
+
+ // Modified |remoting|.
+ first.remoting = std::make_unique<ReceiverSession::RemotingPreferences>();
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second = first;
+
+ second.remoting->supports_4k = true;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ second = first;
+
+ // Modified |video_codecs|.
+ first.video_codecs = {VideoCodec::kVp8, VideoCodec::kVp9};
+ second.video_codecs = {};
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.video_codecs = {VideoCodec::kHevc};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.video_codecs.emplace_back(VideoCodec::kHevc);
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first = second;
+
+ // Modified |audio_codecs|.
+ first.audio_codecs = {AudioCodec::kOpus};
+ second.audio_codecs = {};
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.audio_codecs = {AudioCodec::kAac};
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first.audio_codecs.emplace_back(AudioCodec::kAac);
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ first = second;
+
+ // Modified |video_limits|.
+ first.video_limits.push_back({true, VideoCodec::kVp8});
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.video_limits.front().min_bit_rate = -1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.video_limits.push_back({true, VideoCodec::kVp9});
+ second.video_limits.front().min_bit_rate = -1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.video_limits.front().applies_to_all_codecs = false;
+ first.video_limits.push_back({false, VideoCodec::kHevc, 123});
+ second.video_limits.front().applies_to_all_codecs = false;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.video_limits.front().min_bit_rate = kDefaultVideoMinBitRate;
+ first.video_limits.front().min_bit_rate = kDefaultVideoMinBitRate;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ second = first;
+
+ // Modified |audio_limits|.
+ first.audio_limits.push_back({true, AudioCodec::kOpus});
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.audio_limits.front().min_bit_rate = -1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+ second.audio_limits.push_back({true, AudioCodec::kAac});
+ second.audio_limits.front().min_bit_rate = -1;
+ EXPECT_TRUE(first.IsSupersetOf(second));
+ EXPECT_TRUE(second.IsSupersetOf(first));
+ first.audio_limits.front().applies_to_all_codecs = false;
+ first.audio_limits.push_back({false, AudioCodec::kOpus, -1});
+ second.audio_limits.front().applies_to_all_codecs = false;
+ EXPECT_FALSE(first.IsSupersetOf(second));
+ EXPECT_FALSE(second.IsSupersetOf(first));
+}
+
} // namespace cast
} // namespace openscreen