xref: /aosp_15_r20/external/openscreen/cast/streaming/sender_session_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cast/streaming/sender_session.h"
6 
7 #include <cstdio>
8 #include <utility>
9 
10 #include "cast/streaming/capture_configs.h"
11 #include "cast/streaming/capture_recommendations.h"
12 #include "cast/streaming/mock_environment.h"
13 #include "cast/streaming/testing/simple_message_port.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 #include "platform/base/ip_address.h"
17 #include "platform/test/fake_clock.h"
18 #include "platform/test/fake_task_runner.h"
19 #include "util/chrono_helpers.h"
20 #include "util/stringprintf.h"
21 
22 using ::testing::_;
23 using ::testing::InSequence;
24 using ::testing::Invoke;
25 using ::testing::NiceMock;
26 using ::testing::Return;
27 using ::testing::StrictMock;
28 
29 namespace openscreen {
30 namespace cast {
31 
32 namespace {
33 constexpr char kMalformedAnswerMessage[] = R"({
34   "type": "ANSWER",
35   "seqNum": 1,
36   "answer": {
37     "castMode": "mirroring",
38     "udpPort": 1234,
39     "sendIndexes": [1, 3],
40     "ssrcs": [1, 2]
41 })";
42 
43 constexpr char kValidJsonInvalidFormatAnswerMessage[] = R"({
44   "type": "ANSWER",
45   "seqNum": 1,
46   "answer-2": {
47     "castMode": "mirroring",
48     "udpPort": 1234,
49     "sendIndexes": [1, 3],
50     "ssrcs": [1, 2]
51   }
52 })";
53 
54 constexpr char kValidJsonInvalidAnswerMessage[] = R"({
55   "type": "ANSWER",
56   "seqNum": 1,
57   "answer": {
58     "castMode": "mirroring",
59     "udpPort": -1234,
60     "sendIndexes": [1, 3],
61     "ssrcs": [1, 2]
62   }
63 })";
64 
65 constexpr char kMissingAnswerMessage[] = R"({
66   "type": "ANSWER",
67   "seqNum": 1
68 })";
69 
70 constexpr char kInvalidSequenceNumberMessage[] = R"({
71   "type": "ANSWER",
72   "seqNum": "not actually a number"
73 })";
74 
75 constexpr char kUnknownTypeMessage[] = R"({
76   "type": "ANSWER_VERSION_2",
77   "seqNum": 1
78 })";
79 
80 constexpr char kInvalidTypeMessage[] = R"({
81   "type": 39,
82   "seqNum": 1
83 })";
84 
85 constexpr char kInvalidTypeMessageWithNoSeqNum[] = R"({
86   "type": 39
87 })";
88 
89 constexpr char kErrorAnswerMessage[] = R"({
90   "seqNum": 1,
91   "type": "ANSWER",
92   "result": "error",
93   "error": {
94     "code": 123,
95     "description": "something bad happened"
96   }
97 })";
98 
99 constexpr char kCapabilitiesResponse[] = R"({
100   "seqNum": 2,
101   "result": "ok",
102   "type": "CAPABILITIES_RESPONSE",
103   "capabilities": {
104     "mediaCaps": ["video", "vp8", "audio", "aac"]
105   }
106 })";
107 
108 const AudioCaptureConfig kAudioCaptureConfigInvalidChannels{
109     AudioCodec::kAac, -1 /* channels */, 44000 /* bit_rate */,
110     96000 /* sample_rate */
111 };
112 
113 const AudioCaptureConfig kAudioCaptureConfigValid{
114     AudioCodec::kAac,
115     5 /* channels */,
116     32000 /* bit_rate */,
117     44000 /* sample_rate */,
118     std::chrono::milliseconds(300),
119     "mp4a.40.5"};
120 
121 const VideoCaptureConfig kVideoCaptureConfigMissingResolutions{
122     VideoCodec::kHevc,
123     {60, 1},
124     300000 /* max_bit_rate */,
125     std::vector<Resolution>{},
126     std::chrono::milliseconds(500),
127     "hev1.1.6.L150.B0"};
128 
129 const VideoCaptureConfig kVideoCaptureConfigInvalid{
130     VideoCodec::kHevc,
131     {60, 1},
132     -300000 /* max_bit_rate */,
133     std::vector<Resolution>{Resolution{1920, 1080}, Resolution{1280, 720}}};
134 
135 const VideoCaptureConfig kVideoCaptureConfigValid{
136     VideoCodec::kHevc,
137     {60, 1},
138     300000 /* max_bit_rate */,
139     std::vector<Resolution>{Resolution{1280, 720}, Resolution{1920, 1080}},
140     std::chrono::milliseconds(250),
141     "hev1.1.6.L150.B0"};
142 
143 const VideoCaptureConfig kVideoCaptureConfigValidSimplest{
144     VideoCodec::kHevc,
145     {60, 1},
146     300000 /* max_bit_rate */,
147     std::vector<Resolution>{Resolution{1920, 1080}}};
148 
149 class FakeClient : public SenderSession::Client {
150  public:
151   MOCK_METHOD(void,
152               OnNegotiated,
153               (const SenderSession*,
154                SenderSession::ConfiguredSenders,
155                capture_recommendations::Recommendations),
156               (override));
157   MOCK_METHOD(void,
158               OnRemotingNegotiated,
159               (const SenderSession*, SenderSession::RemotingNegotiation),
160               (override));
161   MOCK_METHOD(void, OnError, (const SenderSession*, Error error), (override));
162 };
163 
164 }  // namespace
165 
166 class SenderSessionTest : public ::testing::Test {
167  public:
SenderSessionTest()168   SenderSessionTest() : clock_(Clock::time_point{}), task_runner_(&clock_) {}
169 
MakeEnvironment()170   std::unique_ptr<MockEnvironment> MakeEnvironment() {
171     auto environment_ = std::make_unique<NiceMock<MockEnvironment>>(
172         &FakeClock::now, &task_runner_);
173     ON_CALL(*environment_, GetBoundLocalEndpoint())
174         .WillByDefault(
175             Return(IPEndpoint{IPAddress::Parse("127.0.0.1").value(), 12345}));
176     return environment_;
177   }
178 
SetUp()179   void SetUp() {
180     message_port_ = std::make_unique<SimpleMessagePort>("receiver-12345");
181     environment_ = MakeEnvironment();
182 
183     SenderSession::Configuration config{IPAddress::kV4LoopbackAddress(),
184                                         &client_,
185                                         environment_.get(),
186                                         message_port_.get(),
187                                         "sender-12345",
188                                         "receiver-12345",
189                                         /* use_android_rtp_hack */ true};
190     session_ = std::make_unique<SenderSession>(std::move(config));
191   }
192 
NegotiateMirroringWithValidConfigs()193   void NegotiateMirroringWithValidConfigs() {
194     const Error error = session_->Negotiate(
195         std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
196         std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
197     ASSERT_TRUE(error.ok());
198   }
199 
NegotiateRemotingWithValidConfigs()200   void NegotiateRemotingWithValidConfigs() {
201     const Error error = session_->NegotiateRemoting(kAudioCaptureConfigValid,
202                                                     kVideoCaptureConfigValid);
203     ASSERT_TRUE(error.ok());
204   }
205 
206   // Answers require specific fields from the original offer to be valid.
ConstructAnswerFromOffer(CastMode mode)207   std::string ConstructAnswerFromOffer(CastMode mode) {
208     const auto& messages = message_port_->posted_messages();
209     if (messages.size() != 1) {
210       return {};
211     }
212     auto message_body = json::Parse(messages[0]);
213     if (message_body.is_error()) {
214       return {};
215     }
216     const Json::Value offer = std::move(message_body.value());
217     EXPECT_EQ("OFFER", offer["type"].asString());
218     EXPECT_LT(0, offer["seqNum"].asInt());
219 
220     const Json::Value& offer_body = offer["offer"];
221     if (!offer_body.isObject()) {
222       return {};
223     }
224 
225     const Json::Value& streams = offer_body["supportedStreams"];
226     EXPECT_TRUE(streams.isArray());
227     EXPECT_EQ(2u, streams.size());
228 
229     const Json::Value& audio_stream = streams[0];
230     const int audio_index = audio_stream["index"].asInt();
231     const int audio_ssrc = audio_stream["ssrc"].asUInt();
232 
233     const Json::Value& video_stream = streams[1];
234     const int video_index = video_stream["index"].asInt();
235     const int video_ssrc = video_stream["ssrc"].asUInt();
236 
237     constexpr char kAnswerTemplate[] = R"({
238         "type": "ANSWER",
239         "seqNum": %d,
240         "result": "ok",
241         "answer": {
242           "castMode": "%s",
243           "udpPort": 1234,
244           "sendIndexes": [%d, %d],
245           "ssrcs": [%d, %d]
246         }
247         })";
248     return StringPrintf(kAnswerTemplate, offer["seqNum"].asInt(),
249                         mode == CastMode::kMirroring ? "mirroring" : "remoting",
250                         audio_index, video_index, audio_ssrc + 1,
251                         video_ssrc + 1);
252   }
253 
254  protected:
255   StrictMock<FakeClient> client_;
256   FakeClock clock_;
257   std::unique_ptr<MockEnvironment> environment_;
258   std::unique_ptr<SimpleMessagePort> message_port_;
259   std::unique_ptr<SenderSession> session_;
260   FakeTaskRunner task_runner_;
261 };
262 
TEST_F(SenderSessionTest,ComplainsIfNoConfigsToOffer)263 TEST_F(SenderSessionTest, ComplainsIfNoConfigsToOffer) {
264   const Error error = session_->Negotiate(std::vector<AudioCaptureConfig>{},
265                                           std::vector<VideoCaptureConfig>{});
266 
267   EXPECT_EQ(error,
268             Error(Error::Code::kParameterInvalid,
269                   "Need at least one audio or video config to negotiate."));
270 }
271 
TEST_F(SenderSessionTest,ComplainsIfInvalidAudioCaptureConfig)272 TEST_F(SenderSessionTest, ComplainsIfInvalidAudioCaptureConfig) {
273   const Error error = session_->Negotiate(
274       std::vector<AudioCaptureConfig>{kAudioCaptureConfigInvalidChannels},
275       std::vector<VideoCaptureConfig>{});
276 
277   EXPECT_EQ(error,
278             Error(Error::Code::kParameterInvalid, "Invalid configs provided."));
279 }
280 
TEST_F(SenderSessionTest,ComplainsIfInvalidVideoCaptureConfig)281 TEST_F(SenderSessionTest, ComplainsIfInvalidVideoCaptureConfig) {
282   const Error error = session_->Negotiate(
283       std::vector<AudioCaptureConfig>{},
284       std::vector<VideoCaptureConfig>{kVideoCaptureConfigInvalid});
285   EXPECT_EQ(error,
286             Error(Error::Code::kParameterInvalid, "Invalid configs provided."));
287 }
288 
TEST_F(SenderSessionTest,ComplainsIfMissingResolutions)289 TEST_F(SenderSessionTest, ComplainsIfMissingResolutions) {
290   const Error error = session_->Negotiate(
291       std::vector<AudioCaptureConfig>{},
292       std::vector<VideoCaptureConfig>{kVideoCaptureConfigMissingResolutions});
293   EXPECT_EQ(error,
294             Error(Error::Code::kParameterInvalid, "Invalid configs provided."));
295 }
296 
TEST_F(SenderSessionTest,SendsOfferWithZeroBitrateOptions)297 TEST_F(SenderSessionTest, SendsOfferWithZeroBitrateOptions) {
298   VideoCaptureConfig video_config = kVideoCaptureConfigValid;
299   video_config.max_bit_rate = 0;
300   AudioCaptureConfig audio_config = kAudioCaptureConfigValid;
301   audio_config.bit_rate = 0;
302 
303   const Error error =
304       session_->Negotiate(std::vector<AudioCaptureConfig>{audio_config},
305                           std::vector<VideoCaptureConfig>{video_config});
306   EXPECT_TRUE(error.ok());
307 
308   const auto& messages = message_port_->posted_messages();
309   ASSERT_EQ(1u, messages.size());
310   auto message_body = json::Parse(messages[0]);
311   ASSERT_TRUE(message_body.is_value());
312   const Json::Value offer = std::move(message_body.value());
313   EXPECT_EQ("OFFER", offer["type"].asString());
314 }
315 
TEST_F(SenderSessionTest,SendsOfferWithSimpleVideoOnly)316 TEST_F(SenderSessionTest, SendsOfferWithSimpleVideoOnly) {
317   const Error error = session_->Negotiate(
318       std::vector<AudioCaptureConfig>{},
319       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
320   EXPECT_TRUE(error.ok());
321 
322   const auto& messages = message_port_->posted_messages();
323   ASSERT_EQ(1u, messages.size());
324   auto message_body = json::Parse(messages[0]);
325   ASSERT_TRUE(message_body.is_value());
326   const Json::Value offer = std::move(message_body.value());
327   EXPECT_EQ("OFFER", offer["type"].asString());
328 }
329 
TEST_F(SenderSessionTest,SendsOfferAudioOnly)330 TEST_F(SenderSessionTest, SendsOfferAudioOnly) {
331   const Error error = session_->Negotiate(
332       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
333       std::vector<VideoCaptureConfig>{});
334   EXPECT_TRUE(error.ok());
335 
336   const auto& messages = message_port_->posted_messages();
337   ASSERT_EQ(1u, messages.size());
338   auto message_body = json::Parse(messages[0]);
339   ASSERT_TRUE(message_body.is_value());
340   const Json::Value offer = std::move(message_body.value());
341   EXPECT_EQ("OFFER", offer["type"].asString());
342 }
343 
TEST_F(SenderSessionTest,SendsOfferMessage)344 TEST_F(SenderSessionTest, SendsOfferMessage) {
345   session_->Negotiate(
346       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
347       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
348 
349   const auto& messages = message_port_->posted_messages();
350   ASSERT_EQ(1u, messages.size());
351 
352   auto message_body = json::Parse(messages[0]);
353   ASSERT_TRUE(message_body.is_value());
354   const Json::Value offer = std::move(message_body.value());
355   EXPECT_EQ("OFFER", offer["type"].asString());
356   EXPECT_LT(0, offer["seqNum"].asInt());
357 
358   const Json::Value& offer_body = offer["offer"];
359   ASSERT_FALSE(offer_body.isNull());
360   ASSERT_TRUE(offer_body.isObject());
361   EXPECT_EQ("mirroring", offer_body["castMode"].asString());
362 
363   const Json::Value& streams = offer_body["supportedStreams"];
364   EXPECT_TRUE(streams.isArray());
365   EXPECT_EQ(2u, streams.size());
366 
367   const Json::Value& audio_stream = streams[0];
368   EXPECT_EQ("aac", audio_stream["codecName"].asString());
369   EXPECT_EQ(0, audio_stream["index"].asInt());
370   EXPECT_EQ(32u, audio_stream["aesKey"].asString().length());
371   EXPECT_EQ(32u, audio_stream["aesIvMask"].asString().length());
372   EXPECT_EQ(5, audio_stream["channels"].asInt());
373   EXPECT_LT(0u, audio_stream["ssrc"].asUInt());
374   EXPECT_EQ(127, audio_stream["rtpPayloadType"].asInt());
375   EXPECT_EQ("mp4a.40.5", audio_stream["codecParameter"].asString());
376 
377   const Json::Value& video_stream = streams[1];
378   EXPECT_EQ("hevc", video_stream["codecName"].asString());
379   EXPECT_EQ(1, video_stream["index"].asInt());
380   EXPECT_EQ(32u, video_stream["aesKey"].asString().length());
381   EXPECT_EQ(32u, video_stream["aesIvMask"].asString().length());
382   EXPECT_EQ(1, video_stream["channels"].asInt());
383   EXPECT_LT(0u, video_stream["ssrc"].asUInt());
384   EXPECT_EQ(96, video_stream["rtpPayloadType"].asInt());
385   EXPECT_EQ("hev1.1.6.L150.B0", video_stream["codecParameter"].asString());
386 }
387 
TEST_F(SenderSessionTest,HandlesValidAnswer)388 TEST_F(SenderSessionTest, HandlesValidAnswer) {
389   NegotiateMirroringWithValidConfigs();
390   std::string answer = ConstructAnswerFromOffer(CastMode::kMirroring);
391 
392   EXPECT_CALL(client_, OnNegotiated(session_.get(), _, _));
393   message_port_->ReceiveMessage(answer);
394 }
395 
TEST_F(SenderSessionTest,HandlesInvalidNamespace)396 TEST_F(SenderSessionTest, HandlesInvalidNamespace) {
397   NegotiateMirroringWithValidConfigs();
398   std::string answer = ConstructAnswerFromOffer(CastMode::kMirroring);
399   message_port_->ReceiveMessage("random-namespace", answer);
400 }
401 
TEST_F(SenderSessionTest,HandlesMalformedAnswer)402 TEST_F(SenderSessionTest, HandlesMalformedAnswer) {
403   session_->Negotiate(
404       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
405       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
406 
407   // Note that unlike when we simply don't select any streams, when the answer
408   // is actually malformed we have no way of knowing it was an answer at all,
409   // so we report an Error and drop the message.
410   EXPECT_CALL(client_, OnError(session_.get(), _));
411   message_port_->ReceiveMessage(kMalformedAnswerMessage);
412 }
413 
TEST_F(SenderSessionTest,HandlesImproperlyFormattedAnswer)414 TEST_F(SenderSessionTest, HandlesImproperlyFormattedAnswer) {
415   session_->Negotiate(
416       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
417       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
418 
419   EXPECT_CALL(client_, OnError(session_.get(), _));
420   message_port_->ReceiveMessage(kValidJsonInvalidFormatAnswerMessage);
421 }
422 
TEST_F(SenderSessionTest,HandlesInvalidAnswer)423 TEST_F(SenderSessionTest, HandlesInvalidAnswer) {
424   const Error error = session_->Negotiate(
425       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
426       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
427 
428   EXPECT_CALL(client_, OnError(session_.get(), _));
429   message_port_->ReceiveMessage(kValidJsonInvalidAnswerMessage);
430 }
431 
TEST_F(SenderSessionTest,HandlesNullAnswer)432 TEST_F(SenderSessionTest, HandlesNullAnswer) {
433   const Error error = session_->Negotiate(
434       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
435       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
436 
437   EXPECT_TRUE(error.ok());
438   EXPECT_CALL(client_, OnError(session_.get(), _));
439   message_port_->ReceiveMessage(kMissingAnswerMessage);
440 }
441 
TEST_F(SenderSessionTest,HandlesInvalidSequenceNumber)442 TEST_F(SenderSessionTest, HandlesInvalidSequenceNumber) {
443   const Error error = session_->Negotiate(
444       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
445       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
446 
447   // We should just discard messages with an invalid sequence number.
448   message_port_->ReceiveMessage(kInvalidSequenceNumberMessage);
449 }
450 
TEST_F(SenderSessionTest,HandlesUnknownTypeMessageWithValidSeqNum)451 TEST_F(SenderSessionTest, HandlesUnknownTypeMessageWithValidSeqNum) {
452   session_->Negotiate(
453       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
454       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
455 
456   // If a message is of unknown type but has an expected seqnum, it's
457   // probably a malformed response.
458   EXPECT_CALL(client_, OnError(session_.get(), _));
459   message_port_->ReceiveMessage(kUnknownTypeMessage);
460 }
461 
TEST_F(SenderSessionTest,HandlesInvalidTypeMessageWithValidSeqNum)462 TEST_F(SenderSessionTest, HandlesInvalidTypeMessageWithValidSeqNum) {
463   session_->Negotiate(
464       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
465       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
466 
467   // If a message is of unknown type but has an expected seqnum, it's
468   // probably a malformed response.
469   EXPECT_CALL(client_, OnError(session_.get(), _));
470   message_port_->ReceiveMessage(kInvalidTypeMessage);
471 }
472 
TEST_F(SenderSessionTest,HandlesInvalidTypeMessage)473 TEST_F(SenderSessionTest, HandlesInvalidTypeMessage) {
474   session_->Negotiate(
475       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
476       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
477 
478   // We should just discard messages with an invalid message type and
479   // no sequence number.
480   message_port_->ReceiveMessage(kInvalidTypeMessageWithNoSeqNum);
481 }
482 
TEST_F(SenderSessionTest,HandlesErrorMessage)483 TEST_F(SenderSessionTest, HandlesErrorMessage) {
484   session_->Negotiate(
485       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
486       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
487 
488   // We should report error answers.
489   EXPECT_CALL(client_, OnError(session_.get(), _));
490   message_port_->ReceiveMessage(kErrorAnswerMessage);
491 }
492 
TEST_F(SenderSessionTest,DoesNotCrashOnMessagePortError)493 TEST_F(SenderSessionTest, DoesNotCrashOnMessagePortError) {
494   session_->Negotiate(
495       std::vector<AudioCaptureConfig>{kAudioCaptureConfigValid},
496       std::vector<VideoCaptureConfig>{kVideoCaptureConfigValid});
497 
498   message_port_->ReceiveError(Error(Error::Code::kUnknownError));
499 }
500 
TEST_F(SenderSessionTest,ReportsZeroBandwidthWhenNoPacketsSent)501 TEST_F(SenderSessionTest, ReportsZeroBandwidthWhenNoPacketsSent) {
502   // TODO(issuetracker.google.com/183996645): As part of end to end testing,
503   // we need to ensure that we are providing reasonable network bandwidth
504   // measurements.
505   EXPECT_EQ(0, session_->GetEstimatedNetworkBandwidth());
506 }
507 
TEST_F(SenderSessionTest,ComplainsIfInvalidAudioCaptureConfigRemoting)508 TEST_F(SenderSessionTest, ComplainsIfInvalidAudioCaptureConfigRemoting) {
509   const Error error = session_->NegotiateRemoting(
510       kAudioCaptureConfigInvalidChannels, kVideoCaptureConfigValid);
511 
512   EXPECT_EQ(error.code(), Error::Code::kParameterInvalid);
513 }
514 
TEST_F(SenderSessionTest,ComplainsIfInvalidVideoCaptureConfigRemoting)515 TEST_F(SenderSessionTest, ComplainsIfInvalidVideoCaptureConfigRemoting) {
516   const Error error = session_->NegotiateRemoting(kAudioCaptureConfigValid,
517                                                   kVideoCaptureConfigInvalid);
518   EXPECT_EQ(error.code(), Error::Code::kParameterInvalid);
519 }
520 
TEST_F(SenderSessionTest,ComplainsIfMissingResolutionsRemoting)521 TEST_F(SenderSessionTest, ComplainsIfMissingResolutionsRemoting) {
522   const Error error = session_->NegotiateRemoting(
523       kAudioCaptureConfigValid, kVideoCaptureConfigMissingResolutions);
524   EXPECT_EQ(error.code(), Error::Code::kParameterInvalid);
525 }
526 
TEST_F(SenderSessionTest,HandlesValidAnswerRemoting)527 TEST_F(SenderSessionTest, HandlesValidAnswerRemoting) {
528   NegotiateRemotingWithValidConfigs();
529   std::string answer = ConstructAnswerFromOffer(CastMode::kRemoting);
530 
531   EXPECT_CALL(client_, OnRemotingNegotiated(session_.get(), _));
532   message_port_->ReceiveMessage(answer);
533   message_port_->ReceiveMessage(kCapabilitiesResponse);
534 }
535 
TEST_F(SenderSessionTest,SuccessfulRemotingNegotiationYieldsValidObject)536 TEST_F(SenderSessionTest, SuccessfulRemotingNegotiationYieldsValidObject) {
537   NegotiateRemotingWithValidConfigs();
538   std::string answer = ConstructAnswerFromOffer(CastMode::kRemoting);
539 
540   SenderSession::RemotingNegotiation negotiation;
541   EXPECT_CALL(client_, OnRemotingNegotiated(session_.get(), _))
542       .WillOnce(testing::SaveArg<1>(&negotiation));
543   message_port_->ReceiveMessage(answer);
544   message_port_->ReceiveMessage(kCapabilitiesResponse);
545 
546   // The capabilities should match the values in |kCapabilitiesResponse|.
547   EXPECT_THAT(negotiation.capabilities.audio,
548               testing::ElementsAre(AudioCapability::kBaselineSet,
549                                    AudioCapability::kAac));
550 
551   // The "video" capability is ignored since it means nothing.
552   EXPECT_THAT(negotiation.capabilities.video,
553               testing::ElementsAre(VideoCapability::kVp8));
554 
555   // The messenger is tested elsewhere, but we can sanity check that we got a valid
556   // one here.
557   EXPECT_TRUE(session_->rpc_messenger());
558   const RpcMessenger::Handle handle =
559       session_->rpc_messenger()->GetUniqueHandle();
560   EXPECT_NE(RpcMessenger::kInvalidHandle, handle);
561 }
562 
563 }  // namespace cast
564 }  // namespace openscreen
565