xref: /aosp_15_r20/external/openscreen/cast/streaming/offer_messages_unittest.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/streaming/offer_messages.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <limits>
8*3f982cf4SFabien Sanglard #include <utility>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include "cast/streaming/rtp_defines.h"
11*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
12*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
13*3f982cf4SFabien Sanglard #include "util/json/json_serialization.h"
14*3f982cf4SFabien Sanglard 
15*3f982cf4SFabien Sanglard using ::testing::ElementsAre;
16*3f982cf4SFabien Sanglard 
17*3f982cf4SFabien Sanglard namespace openscreen {
18*3f982cf4SFabien Sanglard namespace cast {
19*3f982cf4SFabien Sanglard 
20*3f982cf4SFabien Sanglard namespace {
21*3f982cf4SFabien Sanglard 
22*3f982cf4SFabien Sanglard constexpr char kValidOffer[] = R"({
23*3f982cf4SFabien Sanglard   "castMode": "mirroring",
24*3f982cf4SFabien Sanglard   "supportedStreams": [
25*3f982cf4SFabien Sanglard     {
26*3f982cf4SFabien Sanglard       "index": 0,
27*3f982cf4SFabien Sanglard       "type": "video_source",
28*3f982cf4SFabien Sanglard       "codecName": "h264",
29*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
30*3f982cf4SFabien Sanglard       "rtpPayloadType": 101,
31*3f982cf4SFabien Sanglard       "ssrc": 19088743,
32*3f982cf4SFabien Sanglard       "maxFrameRate": "60000/1000",
33*3f982cf4SFabien Sanglard       "timeBase": "1/90000",
34*3f982cf4SFabien Sanglard       "maxBitRate": 5000000,
35*3f982cf4SFabien Sanglard       "profile": "main",
36*3f982cf4SFabien Sanglard       "level": "4",
37*3f982cf4SFabien Sanglard       "targetDelay": 200,
38*3f982cf4SFabien Sanglard       "aesKey": "040d756791711fd3adb939066e6d8690",
39*3f982cf4SFabien Sanglard       "aesIvMask": "9ff0f022a959150e70a2d05a6c184aed",
40*3f982cf4SFabien Sanglard       "resolutions": [
41*3f982cf4SFabien Sanglard         {
42*3f982cf4SFabien Sanglard           "width": 1280,
43*3f982cf4SFabien Sanglard           "height": 720
44*3f982cf4SFabien Sanglard         },
45*3f982cf4SFabien Sanglard         {
46*3f982cf4SFabien Sanglard           "width": 640,
47*3f982cf4SFabien Sanglard           "height": 360
48*3f982cf4SFabien Sanglard         },
49*3f982cf4SFabien Sanglard         {
50*3f982cf4SFabien Sanglard           "width": 640,
51*3f982cf4SFabien Sanglard           "height": 480
52*3f982cf4SFabien Sanglard         }
53*3f982cf4SFabien Sanglard       ]
54*3f982cf4SFabien Sanglard     },
55*3f982cf4SFabien Sanglard     {
56*3f982cf4SFabien Sanglard       "index": 1,
57*3f982cf4SFabien Sanglard       "type": "video_source",
58*3f982cf4SFabien Sanglard       "codecName": "vp8",
59*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
60*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
61*3f982cf4SFabien Sanglard       "ssrc": 19088744,
62*3f982cf4SFabien Sanglard       "maxFrameRate": "30000/1001",
63*3f982cf4SFabien Sanglard       "targetDelay": 1000,
64*3f982cf4SFabien Sanglard       "timeBase": "1/90000",
65*3f982cf4SFabien Sanglard       "maxBitRate": 5000000,
66*3f982cf4SFabien Sanglard       "profile": "main",
67*3f982cf4SFabien Sanglard       "level": "5",
68*3f982cf4SFabien Sanglard       "aesKey": "bbf109bf84513b456b13a184453b66ce",
69*3f982cf4SFabien Sanglard       "aesIvMask": "edaf9e4536e2b66191f560d9c04b2a69"
70*3f982cf4SFabien Sanglard     },
71*3f982cf4SFabien Sanglard     {
72*3f982cf4SFabien Sanglard       "index": 2,
73*3f982cf4SFabien Sanglard       "type": "audio_source",
74*3f982cf4SFabien Sanglard       "codecName": "opus",
75*3f982cf4SFabien Sanglard       "targetDelay": 300,
76*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
77*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
78*3f982cf4SFabien Sanglard       "ssrc": 4294967295,
79*3f982cf4SFabien Sanglard       "bitRate": 124000,
80*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
81*3f982cf4SFabien Sanglard       "channels": 2,
82*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
83*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
84*3f982cf4SFabien Sanglard     },
85*3f982cf4SFabien Sanglard     {
86*3f982cf4SFabien Sanglard       "index": 3,
87*3f982cf4SFabien Sanglard       "type": "video_source",
88*3f982cf4SFabien Sanglard       "codecName": "av1",
89*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
90*3f982cf4SFabien Sanglard       "rtpPayloadType": 104,
91*3f982cf4SFabien Sanglard       "ssrc": 19088744,
92*3f982cf4SFabien Sanglard       "maxFrameRate": "30000/1001",
93*3f982cf4SFabien Sanglard       "targetDelay": 1000,
94*3f982cf4SFabien Sanglard       "timeBase": "1/90000",
95*3f982cf4SFabien Sanglard       "maxBitRate": 5000000,
96*3f982cf4SFabien Sanglard       "profile": "main",
97*3f982cf4SFabien Sanglard       "level": "5",
98*3f982cf4SFabien Sanglard       "aesKey": "bbf109bf84513b456b13a184453b66ce",
99*3f982cf4SFabien Sanglard       "aesIvMask": "edaf9e4536e2b66191f560d9c04b2a69"
100*3f982cf4SFabien Sanglard     }
101*3f982cf4SFabien Sanglard   ]
102*3f982cf4SFabien Sanglard })";
103*3f982cf4SFabien Sanglard 
ExpectFailureOnParse(absl::string_view body,absl::optional<Error::Code> expected=absl::nullopt)104*3f982cf4SFabien Sanglard void ExpectFailureOnParse(
105*3f982cf4SFabien Sanglard     absl::string_view body,
106*3f982cf4SFabien Sanglard     absl::optional<Error::Code> expected = absl::nullopt) {
107*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(body);
108*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value()) << root.error();
109*3f982cf4SFabien Sanglard 
110*3f982cf4SFabien Sanglard   Offer offer;
111*3f982cf4SFabien Sanglard   Error error = Offer::TryParse(std::move(root.value()), &offer);
112*3f982cf4SFabien Sanglard   EXPECT_FALSE(error.ok());
113*3f982cf4SFabien Sanglard   if (expected) {
114*3f982cf4SFabien Sanglard     EXPECT_EQ(expected, error.code());
115*3f982cf4SFabien Sanglard   }
116*3f982cf4SFabien Sanglard }
117*3f982cf4SFabien Sanglard 
ExpectEqualsValidOffer(const Offer & offer)118*3f982cf4SFabien Sanglard void ExpectEqualsValidOffer(const Offer& offer) {
119*3f982cf4SFabien Sanglard   EXPECT_EQ(CastMode::kMirroring, offer.cast_mode);
120*3f982cf4SFabien Sanglard 
121*3f982cf4SFabien Sanglard   // Verify list of video streams.
122*3f982cf4SFabien Sanglard   EXPECT_EQ(3u, offer.video_streams.size());
123*3f982cf4SFabien Sanglard   const auto& video_streams = offer.video_streams;
124*3f982cf4SFabien Sanglard 
125*3f982cf4SFabien Sanglard   const bool flipped = video_streams[0].stream.index != 0;
126*3f982cf4SFabien Sanglard   const VideoStream& vs_one = flipped ? video_streams[2] : video_streams[0];
127*3f982cf4SFabien Sanglard   const VideoStream& vs_two = video_streams[1];
128*3f982cf4SFabien Sanglard   const VideoStream& vs_three = flipped ? video_streams[0] : video_streams[2];
129*3f982cf4SFabien Sanglard 
130*3f982cf4SFabien Sanglard   EXPECT_EQ(0, vs_one.stream.index);
131*3f982cf4SFabien Sanglard   EXPECT_EQ(1, vs_one.stream.channels);
132*3f982cf4SFabien Sanglard   EXPECT_EQ(Stream::Type::kVideoSource, vs_one.stream.type);
133*3f982cf4SFabien Sanglard   EXPECT_EQ(VideoCodec::kH264, vs_one.codec);
134*3f982cf4SFabien Sanglard   EXPECT_EQ(RtpPayloadType::kVideoH264, vs_one.stream.rtp_payload_type);
135*3f982cf4SFabien Sanglard   EXPECT_EQ(19088743u, vs_one.stream.ssrc);
136*3f982cf4SFabien Sanglard   EXPECT_EQ((SimpleFraction{60000, 1000}), vs_one.max_frame_rate);
137*3f982cf4SFabien Sanglard   EXPECT_EQ(90000, vs_one.stream.rtp_timebase);
138*3f982cf4SFabien Sanglard   EXPECT_EQ(5000000, vs_one.max_bit_rate);
139*3f982cf4SFabien Sanglard   EXPECT_EQ("main", vs_one.profile);
140*3f982cf4SFabien Sanglard   EXPECT_EQ("4", vs_one.level);
141*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_one.stream.aes_key,
142*3f982cf4SFabien Sanglard               ElementsAre(0x04, 0x0d, 0x75, 0x67, 0x91, 0x71, 0x1f, 0xd3, 0xad,
143*3f982cf4SFabien Sanglard                           0xb9, 0x39, 0x06, 0x6e, 0x6d, 0x86, 0x90));
144*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_one.stream.aes_iv_mask,
145*3f982cf4SFabien Sanglard               ElementsAre(0x9f, 0xf0, 0xf0, 0x22, 0xa9, 0x59, 0x15, 0x0e, 0x70,
146*3f982cf4SFabien Sanglard                           0xa2, 0xd0, 0x5a, 0x6c, 0x18, 0x4a, 0xed));
147*3f982cf4SFabien Sanglard 
148*3f982cf4SFabien Sanglard   const auto& resolutions = vs_one.resolutions;
149*3f982cf4SFabien Sanglard   EXPECT_EQ(3u, resolutions.size());
150*3f982cf4SFabien Sanglard   const Resolution& r_one = resolutions[0];
151*3f982cf4SFabien Sanglard   EXPECT_EQ(1280, r_one.width);
152*3f982cf4SFabien Sanglard   EXPECT_EQ(720, r_one.height);
153*3f982cf4SFabien Sanglard 
154*3f982cf4SFabien Sanglard   const Resolution& r_two = resolutions[1];
155*3f982cf4SFabien Sanglard   EXPECT_EQ(640, r_two.width);
156*3f982cf4SFabien Sanglard   EXPECT_EQ(360, r_two.height);
157*3f982cf4SFabien Sanglard 
158*3f982cf4SFabien Sanglard   const Resolution& r_three = resolutions[2];
159*3f982cf4SFabien Sanglard   EXPECT_EQ(640, r_three.width);
160*3f982cf4SFabien Sanglard   EXPECT_EQ(480, r_three.height);
161*3f982cf4SFabien Sanglard 
162*3f982cf4SFabien Sanglard   EXPECT_EQ(1, vs_two.stream.index);
163*3f982cf4SFabien Sanglard   EXPECT_EQ(1, vs_two.stream.channels);
164*3f982cf4SFabien Sanglard   EXPECT_EQ(Stream::Type::kVideoSource, vs_two.stream.type);
165*3f982cf4SFabien Sanglard   EXPECT_EQ(VideoCodec::kVp8, vs_two.codec);
166*3f982cf4SFabien Sanglard   EXPECT_EQ(RtpPayloadType::kVideoVp8, vs_two.stream.rtp_payload_type);
167*3f982cf4SFabien Sanglard   EXPECT_EQ(19088744u, vs_two.stream.ssrc);
168*3f982cf4SFabien Sanglard   EXPECT_EQ((SimpleFraction{30000, 1001}), vs_two.max_frame_rate);
169*3f982cf4SFabien Sanglard   EXPECT_EQ(90000, vs_two.stream.rtp_timebase);
170*3f982cf4SFabien Sanglard   EXPECT_EQ(5000000, vs_two.max_bit_rate);
171*3f982cf4SFabien Sanglard   EXPECT_EQ("main", vs_two.profile);
172*3f982cf4SFabien Sanglard   EXPECT_EQ("5", vs_two.level);
173*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_two.stream.aes_key,
174*3f982cf4SFabien Sanglard               ElementsAre(0xbb, 0xf1, 0x09, 0xbf, 0x84, 0x51, 0x3b, 0x45, 0x6b,
175*3f982cf4SFabien Sanglard                           0x13, 0xa1, 0x84, 0x45, 0x3b, 0x66, 0xce));
176*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_two.stream.aes_iv_mask,
177*3f982cf4SFabien Sanglard               ElementsAre(0xed, 0xaf, 0x9e, 0x45, 0x36, 0xe2, 0xb6, 0x61, 0x91,
178*3f982cf4SFabien Sanglard                           0xf5, 0x60, 0xd9, 0xc0, 0x4b, 0x2a, 0x69));
179*3f982cf4SFabien Sanglard 
180*3f982cf4SFabien Sanglard   const auto& resolutions_two = vs_two.resolutions;
181*3f982cf4SFabien Sanglard   EXPECT_EQ(0u, resolutions_two.size());
182*3f982cf4SFabien Sanglard 
183*3f982cf4SFabien Sanglard   EXPECT_EQ(3, vs_three.stream.index);
184*3f982cf4SFabien Sanglard   EXPECT_EQ(1, vs_three.stream.channels);
185*3f982cf4SFabien Sanglard   EXPECT_EQ(Stream::Type::kVideoSource, vs_three.stream.type);
186*3f982cf4SFabien Sanglard   EXPECT_EQ(VideoCodec::kAv1, vs_three.codec);
187*3f982cf4SFabien Sanglard   EXPECT_EQ(RtpPayloadType::kVideoAv1, vs_three.stream.rtp_payload_type);
188*3f982cf4SFabien Sanglard   EXPECT_EQ(19088744u, vs_three.stream.ssrc);
189*3f982cf4SFabien Sanglard   EXPECT_EQ((SimpleFraction{30000, 1001}), vs_three.max_frame_rate);
190*3f982cf4SFabien Sanglard   EXPECT_EQ(90000, vs_three.stream.rtp_timebase);
191*3f982cf4SFabien Sanglard   EXPECT_EQ(5000000, vs_three.max_bit_rate);
192*3f982cf4SFabien Sanglard   EXPECT_EQ("main", vs_three.profile);
193*3f982cf4SFabien Sanglard   EXPECT_EQ("5", vs_three.level);
194*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_three.stream.aes_key,
195*3f982cf4SFabien Sanglard               ElementsAre(0xbb, 0xf1, 0x09, 0xbf, 0x84, 0x51, 0x3b, 0x45, 0x6b,
196*3f982cf4SFabien Sanglard                           0x13, 0xa1, 0x84, 0x45, 0x3b, 0x66, 0xce));
197*3f982cf4SFabien Sanglard   EXPECT_THAT(vs_three.stream.aes_iv_mask,
198*3f982cf4SFabien Sanglard               ElementsAre(0xed, 0xaf, 0x9e, 0x45, 0x36, 0xe2, 0xb6, 0x61, 0x91,
199*3f982cf4SFabien Sanglard                           0xf5, 0x60, 0xd9, 0xc0, 0x4b, 0x2a, 0x69));
200*3f982cf4SFabien Sanglard 
201*3f982cf4SFabien Sanglard   const auto& resolutions_three = vs_three.resolutions;
202*3f982cf4SFabien Sanglard   EXPECT_EQ(0u, resolutions_three.size());
203*3f982cf4SFabien Sanglard 
204*3f982cf4SFabien Sanglard   // Verify list of audio streams.
205*3f982cf4SFabien Sanglard   EXPECT_EQ(1u, offer.audio_streams.size());
206*3f982cf4SFabien Sanglard   const AudioStream& as = offer.audio_streams[0];
207*3f982cf4SFabien Sanglard   EXPECT_EQ(2, as.stream.index);
208*3f982cf4SFabien Sanglard   EXPECT_EQ(Stream::Type::kAudioSource, as.stream.type);
209*3f982cf4SFabien Sanglard   EXPECT_EQ(AudioCodec::kOpus, as.codec);
210*3f982cf4SFabien Sanglard   EXPECT_EQ(RtpPayloadType::kAudioOpus, as.stream.rtp_payload_type);
211*3f982cf4SFabien Sanglard   EXPECT_EQ(std::numeric_limits<Ssrc>::max(), as.stream.ssrc);
212*3f982cf4SFabien Sanglard   EXPECT_EQ(124000, as.bit_rate);
213*3f982cf4SFabien Sanglard   EXPECT_EQ(2, as.stream.channels);
214*3f982cf4SFabien Sanglard 
215*3f982cf4SFabien Sanglard   EXPECT_THAT(as.stream.aes_key,
216*3f982cf4SFabien Sanglard               ElementsAre(0x51, 0x02, 0x7e, 0x4e, 0x23, 0x47, 0xcb, 0xcb, 0x49,
217*3f982cf4SFabien Sanglard                           0xd5, 0x7e, 0xf1, 0x01, 0x77, 0xae, 0xbc));
218*3f982cf4SFabien Sanglard   EXPECT_THAT(as.stream.aes_iv_mask,
219*3f982cf4SFabien Sanglard               ElementsAre(0x7f, 0x12, 0xa1, 0x9b, 0xe6, 0x2a, 0x36, 0xc0, 0x4a,
220*3f982cf4SFabien Sanglard                           0xe4, 0x11, 0x6c, 0xaa, 0xef, 0xf6, 0xd1));
221*3f982cf4SFabien Sanglard }
222*3f982cf4SFabien Sanglard 
223*3f982cf4SFabien Sanglard }  // namespace
224*3f982cf4SFabien Sanglard 
TEST(OfferTest,ErrorOnEmptyOffer)225*3f982cf4SFabien Sanglard TEST(OfferTest, ErrorOnEmptyOffer) {
226*3f982cf4SFabien Sanglard   ExpectFailureOnParse("{}");
227*3f982cf4SFabien Sanglard }
228*3f982cf4SFabien Sanglard 
TEST(OfferTest,ErrorOnMissingMandatoryFields)229*3f982cf4SFabien Sanglard TEST(OfferTest, ErrorOnMissingMandatoryFields) {
230*3f982cf4SFabien Sanglard   // It's okay if castMode is omitted, but if supportedStreams is omitted we
231*3f982cf4SFabien Sanglard   // should fail here.
232*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
233*3f982cf4SFabien Sanglard     "castMode": "mirroring"
234*3f982cf4SFabien Sanglard   })");
235*3f982cf4SFabien Sanglard }
236*3f982cf4SFabien Sanglard 
TEST(OfferTest,CanParseValidButStreamlessOffer)237*3f982cf4SFabien Sanglard TEST(OfferTest, CanParseValidButStreamlessOffer) {
238*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(R"({
239*3f982cf4SFabien Sanglard     "castMode": "mirroring",
240*3f982cf4SFabien Sanglard     "supportedStreams": []
241*3f982cf4SFabien Sanglard   })");
242*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value()) << root.error();
243*3f982cf4SFabien Sanglard 
244*3f982cf4SFabien Sanglard   Offer offer;
245*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
246*3f982cf4SFabien Sanglard }
247*3f982cf4SFabien Sanglard 
TEST(OfferTest,ErrorOnMissingAudioStreamMandatoryField)248*3f982cf4SFabien Sanglard TEST(OfferTest, ErrorOnMissingAudioStreamMandatoryField) {
249*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
250*3f982cf4SFabien Sanglard     "castMode": "mirroring",
251*3f982cf4SFabien Sanglard     "supportedStreams": [{
252*3f982cf4SFabien Sanglard       "index": 2,
253*3f982cf4SFabien Sanglard       "codecName": "opus",
254*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
255*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
256*3f982cf4SFabien Sanglard       "ssrc": 19088743,
257*3f982cf4SFabien Sanglard       "bitRate": 124000,
258*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
259*3f982cf4SFabien Sanglard       "channels": 2
260*3f982cf4SFabien Sanglard     }]})");
261*3f982cf4SFabien Sanglard 
262*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
263*3f982cf4SFabien Sanglard     "castMode": "mirroring",
264*3f982cf4SFabien Sanglard     "supportedStreams": [{
265*3f982cf4SFabien Sanglard       "index": 2,
266*3f982cf4SFabien Sanglard       "type": "audio_source",
267*3f982cf4SFabien Sanglard       "codecName": "opus",
268*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
269*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
270*3f982cf4SFabien Sanglard       "bitRate": 124000,
271*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
272*3f982cf4SFabien Sanglard       "channels": 2
273*3f982cf4SFabien Sanglard     }]})");
274*3f982cf4SFabien Sanglard }
275*3f982cf4SFabien Sanglard 
TEST(OfferTest,CanParseValidButMinimalAudioOffer)276*3f982cf4SFabien Sanglard TEST(OfferTest, CanParseValidButMinimalAudioOffer) {
277*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(R"({
278*3f982cf4SFabien Sanglard     "castMode": "mirroring",
279*3f982cf4SFabien Sanglard     "supportedStreams": [{
280*3f982cf4SFabien Sanglard       "index": 2,
281*3f982cf4SFabien Sanglard       "type": "audio_source",
282*3f982cf4SFabien Sanglard       "codecName": "opus",
283*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
284*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
285*3f982cf4SFabien Sanglard       "ssrc": 19088743,
286*3f982cf4SFabien Sanglard       "bitRate": 124000,
287*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
288*3f982cf4SFabien Sanglard       "channels": 2,
289*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
290*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
291*3f982cf4SFabien Sanglard     }]
292*3f982cf4SFabien Sanglard   })");
293*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
294*3f982cf4SFabien Sanglard   Offer offer;
295*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
296*3f982cf4SFabien Sanglard }
297*3f982cf4SFabien Sanglard 
TEST(OfferTest,CanParseValidZeroBitRateAudioOffer)298*3f982cf4SFabien Sanglard TEST(OfferTest, CanParseValidZeroBitRateAudioOffer) {
299*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(R"({
300*3f982cf4SFabien Sanglard     "castMode": "mirroring",
301*3f982cf4SFabien Sanglard     "supportedStreams": [{
302*3f982cf4SFabien Sanglard       "index": 2,
303*3f982cf4SFabien Sanglard       "type": "audio_source",
304*3f982cf4SFabien Sanglard       "codecName": "opus",
305*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
306*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
307*3f982cf4SFabien Sanglard       "ssrc": 19088743,
308*3f982cf4SFabien Sanglard       "bitRate": 0,
309*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
310*3f982cf4SFabien Sanglard       "channels": 5,
311*3f982cf4SFabien Sanglard       "aesKey": "51029e4e2347cbcb49d57ef10177aebd",
312*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff5d2"
313*3f982cf4SFabien Sanglard     }]
314*3f982cf4SFabien Sanglard   })");
315*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value()) << root.error();
316*3f982cf4SFabien Sanglard   Offer offer;
317*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
318*3f982cf4SFabien Sanglard }
319*3f982cf4SFabien Sanglard 
TEST(OfferTest,ErrorOnInvalidRtpTimebase)320*3f982cf4SFabien Sanglard TEST(OfferTest, ErrorOnInvalidRtpTimebase) {
321*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
322*3f982cf4SFabien Sanglard     "castMode": "mirroring",
323*3f982cf4SFabien Sanglard     "supportedStreams": [{
324*3f982cf4SFabien Sanglard       "index": 2,
325*3f982cf4SFabien Sanglard       "type": "audio_source",
326*3f982cf4SFabien Sanglard       "codecName": "opus",
327*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
328*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
329*3f982cf4SFabien Sanglard       "ssrc": 19088743,
330*3f982cf4SFabien Sanglard       "bitRate": 124000,
331*3f982cf4SFabien Sanglard       "timeBase": "1/10000000",
332*3f982cf4SFabien Sanglard       "channels": 2,
333*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
334*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
335*3f982cf4SFabien Sanglard     }]
336*3f982cf4SFabien Sanglard   })");
337*3f982cf4SFabien Sanglard 
338*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
339*3f982cf4SFabien Sanglard     "castMode": "mirroring",
340*3f982cf4SFabien Sanglard     "supportedStreams": [{
341*3f982cf4SFabien Sanglard       "index": 2,
342*3f982cf4SFabien Sanglard       "type": "audio_source",
343*3f982cf4SFabien Sanglard       "codecName": "opus",
344*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
345*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
346*3f982cf4SFabien Sanglard       "ssrc": 19088743,
347*3f982cf4SFabien Sanglard       "bitRate": 124000,
348*3f982cf4SFabien Sanglard       "timeBase": "0",
349*3f982cf4SFabien Sanglard       "channels": 2,
350*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
351*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
352*3f982cf4SFabien Sanglard     }]
353*3f982cf4SFabien Sanglard   })");
354*3f982cf4SFabien Sanglard 
355*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
356*3f982cf4SFabien Sanglard     "castMode": "mirroring",
357*3f982cf4SFabien Sanglard     "supportedStreams": [{
358*3f982cf4SFabien Sanglard       "index": 2,
359*3f982cf4SFabien Sanglard       "type": "audio_source",
360*3f982cf4SFabien Sanglard       "codecName": "opus",
361*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
362*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
363*3f982cf4SFabien Sanglard       "ssrc": 19088743,
364*3f982cf4SFabien Sanglard       "bitRate": 124000,
365*3f982cf4SFabien Sanglard       "timeBase": "1/1",
366*3f982cf4SFabien Sanglard       "channels": 2,
367*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
368*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
369*3f982cf4SFabien Sanglard     }]
370*3f982cf4SFabien Sanglard   })");
371*3f982cf4SFabien Sanglard 
372*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
373*3f982cf4SFabien Sanglard     "castMode": "mirroring",
374*3f982cf4SFabien Sanglard     "supportedStreams": [{
375*3f982cf4SFabien Sanglard       "index": 2,
376*3f982cf4SFabien Sanglard       "type": "audio_source",
377*3f982cf4SFabien Sanglard       "codecName": "opus",
378*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
379*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
380*3f982cf4SFabien Sanglard       "ssrc": 19088743,
381*3f982cf4SFabien Sanglard       "bitRate": 124000,
382*3f982cf4SFabien Sanglard       "timeBase": "really fast plz, kthx",
383*3f982cf4SFabien Sanglard       "channels": 2,
384*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
385*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
386*3f982cf4SFabien Sanglard     }]
387*3f982cf4SFabien Sanglard   })");
388*3f982cf4SFabien Sanglard }
389*3f982cf4SFabien Sanglard 
TEST(OfferTest,ErrorOnMissingVideoStreamMandatoryField)390*3f982cf4SFabien Sanglard TEST(OfferTest, ErrorOnMissingVideoStreamMandatoryField) {
391*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
392*3f982cf4SFabien Sanglard     "castMode": "mirroring",
393*3f982cf4SFabien Sanglard     "supportedStreams": [{
394*3f982cf4SFabien Sanglard       "index": 2,
395*3f982cf4SFabien Sanglard       "codecName": "video_source",
396*3f982cf4SFabien Sanglard       "rtpProfile": "h264",
397*3f982cf4SFabien Sanglard       "rtpPayloadType": 101,
398*3f982cf4SFabien Sanglard       "ssrc": 19088743,
399*3f982cf4SFabien Sanglard       "bitRate": 124000,
400*3f982cf4SFabien Sanglard       "timeBase": "1/48000"
401*3f982cf4SFabien Sanglard     }]
402*3f982cf4SFabien Sanglard   })");
403*3f982cf4SFabien Sanglard 
404*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
405*3f982cf4SFabien Sanglard     "castMode": "mirroring",
406*3f982cf4SFabien Sanglard     "supportedStreams": [{
407*3f982cf4SFabien Sanglard       "index": 2,
408*3f982cf4SFabien Sanglard       "type": "video_source",
409*3f982cf4SFabien Sanglard       "codecName": "h264",
410*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
411*3f982cf4SFabien Sanglard       "rtpPayloadType": 101,
412*3f982cf4SFabien Sanglard       "bitRate": 124000,
413*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
414*3f982cf4SFabien Sanglard        "maxBitRate": 10000
415*3f982cf4SFabien Sanglard     }]
416*3f982cf4SFabien Sanglard   })");
417*3f982cf4SFabien Sanglard 
418*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
419*3f982cf4SFabien Sanglard     "castMode": "mirroring",
420*3f982cf4SFabien Sanglard     "supportedStreams": [{
421*3f982cf4SFabien Sanglard       "index": 2,
422*3f982cf4SFabien Sanglard       "type": "video_source",
423*3f982cf4SFabien Sanglard       "codecName": "vp8",
424*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
425*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
426*3f982cf4SFabien Sanglard       "ssrc": 19088743,
427*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
428*3f982cf4SFabien Sanglard        "resolutions": [],
429*3f982cf4SFabien Sanglard        "maxBitRate": 10000
430*3f982cf4SFabien Sanglard     }]
431*3f982cf4SFabien Sanglard   })");
432*3f982cf4SFabien Sanglard 
433*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
434*3f982cf4SFabien Sanglard     "castMode": "mirroring",
435*3f982cf4SFabien Sanglard     "supportedStreams": [{
436*3f982cf4SFabien Sanglard       "index": 2,
437*3f982cf4SFabien Sanglard       "type": "video_source",
438*3f982cf4SFabien Sanglard       "codecName": "vp8",
439*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
440*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
441*3f982cf4SFabien Sanglard       "ssrc": 19088743,
442*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
443*3f982cf4SFabien Sanglard        "resolutions": [],
444*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
445*3f982cf4SFabien Sanglard        "aesKey": "51027e4e2347cbcb49d57ef10177aebc"
446*3f982cf4SFabien Sanglard     }]
447*3f982cf4SFabien Sanglard   })");
448*3f982cf4SFabien Sanglard 
449*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
450*3f982cf4SFabien Sanglard     "castMode": "mirroring",
451*3f982cf4SFabien Sanglard     "supportedStreams": [{
452*3f982cf4SFabien Sanglard       "index": 2,
453*3f982cf4SFabien Sanglard       "type": "video_source",
454*3f982cf4SFabien Sanglard       "codecName": "vp8",
455*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
456*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
457*3f982cf4SFabien Sanglard       "ssrc": 19088743,
458*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
459*3f982cf4SFabien Sanglard        "resolutions": [],
460*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
461*3f982cf4SFabien Sanglard        "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
462*3f982cf4SFabien Sanglard     }]
463*3f982cf4SFabien Sanglard   })");
464*3f982cf4SFabien Sanglard }
465*3f982cf4SFabien Sanglard 
TEST(OfferTest,ValidatesCodecParameterFormat)466*3f982cf4SFabien Sanglard TEST(OfferTest, ValidatesCodecParameterFormat) {
467*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
468*3f982cf4SFabien Sanglard     "castMode": "mirroring",
469*3f982cf4SFabien Sanglard     "supportedStreams": [{
470*3f982cf4SFabien Sanglard       "index": 2,
471*3f982cf4SFabien Sanglard       "type": "audio_source",
472*3f982cf4SFabien Sanglard       "codecName": "aac",
473*3f982cf4SFabien Sanglard       "codecParameter": "vp08.123.332",
474*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
475*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
476*3f982cf4SFabien Sanglard       "ssrc": 19088743,
477*3f982cf4SFabien Sanglard       "bitRate": 124000,
478*3f982cf4SFabien Sanglard       "timeBase": "1/10000000",
479*3f982cf4SFabien Sanglard       "channels": 2,
480*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
481*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
482*3f982cf4SFabien Sanglard     }]
483*3f982cf4SFabien Sanglard   })");
484*3f982cf4SFabien Sanglard 
485*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
486*3f982cf4SFabien Sanglard     "castMode": "mirroring",
487*3f982cf4SFabien Sanglard     "supportedStreams": [{
488*3f982cf4SFabien Sanglard       "index": 2,
489*3f982cf4SFabien Sanglard       "type": "video_source",
490*3f982cf4SFabien Sanglard       "codecName": "vp8",
491*3f982cf4SFabien Sanglard       "codecParameter": "vp09.11.23",
492*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
493*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
494*3f982cf4SFabien Sanglard       "ssrc": 19088743,
495*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
496*3f982cf4SFabien Sanglard        "resolutions": [],
497*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
498*3f982cf4SFabien Sanglard        "aesKey": "51027e4e2347cbcb49d57ef10177aebc"
499*3f982cf4SFabien Sanglard     }]
500*3f982cf4SFabien Sanglard   })");
501*3f982cf4SFabien Sanglard 
502*3f982cf4SFabien Sanglard   const ErrorOr<Json::Value> audio_root = json::Parse(R"({
503*3f982cf4SFabien Sanglard     "castMode": "mirroring",
504*3f982cf4SFabien Sanglard     "supportedStreams": [{
505*3f982cf4SFabien Sanglard       "index": 2,
506*3f982cf4SFabien Sanglard       "type": "audio_source",
507*3f982cf4SFabien Sanglard       "codecName": "aac",
508*3f982cf4SFabien Sanglard       "codecParameter": "mp4a.12",
509*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
510*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
511*3f982cf4SFabien Sanglard       "ssrc": 19088743,
512*3f982cf4SFabien Sanglard       "bitRate": 124000,
513*3f982cf4SFabien Sanglard       "timeBase": "1/10000000",
514*3f982cf4SFabien Sanglard       "channels": 2,
515*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
516*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
517*3f982cf4SFabien Sanglard     }]
518*3f982cf4SFabien Sanglard   })");
519*3f982cf4SFabien Sanglard   ASSERT_TRUE(audio_root.is_value()) << audio_root.error();
520*3f982cf4SFabien Sanglard 
521*3f982cf4SFabien Sanglard   const ErrorOr<Json::Value> video_root = json::Parse(R"({
522*3f982cf4SFabien Sanglard     "castMode": "mirroring",
523*3f982cf4SFabien Sanglard     "supportedStreams": [{
524*3f982cf4SFabien Sanglard       "index": 2,
525*3f982cf4SFabien Sanglard       "type": "video_source",
526*3f982cf4SFabien Sanglard       "codecName": "vp9",
527*3f982cf4SFabien Sanglard       "codecParameter": "vp09.11.23",
528*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
529*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
530*3f982cf4SFabien Sanglard       "ssrc": 19088743,
531*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
532*3f982cf4SFabien Sanglard        "resolutions": [],
533*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
534*3f982cf4SFabien Sanglard        "aesKey": "51027e4e2347cbcb49d57ef10177aebc"
535*3f982cf4SFabien Sanglard     }]
536*3f982cf4SFabien Sanglard   })");
537*3f982cf4SFabien Sanglard   ASSERT_TRUE(video_root.is_value()) << video_root.error();
538*3f982cf4SFabien Sanglard }
539*3f982cf4SFabien Sanglard 
TEST(OfferTest,CanParseValidButMinimalVideoOffer)540*3f982cf4SFabien Sanglard TEST(OfferTest, CanParseValidButMinimalVideoOffer) {
541*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(R"({
542*3f982cf4SFabien Sanglard     "castMode": "mirroring",
543*3f982cf4SFabien Sanglard     "supportedStreams": [{
544*3f982cf4SFabien Sanglard       "index": 2,
545*3f982cf4SFabien Sanglard       "type": "video_source",
546*3f982cf4SFabien Sanglard       "codecName": "vp8",
547*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
548*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
549*3f982cf4SFabien Sanglard       "ssrc": 19088743,
550*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
551*3f982cf4SFabien Sanglard        "resolutions": [],
552*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
553*3f982cf4SFabien Sanglard        "aesKey": "51027e4e2347cbcb49d57ef10177aebc",
554*3f982cf4SFabien Sanglard        "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
555*3f982cf4SFabien Sanglard     }]
556*3f982cf4SFabien Sanglard   })");
557*3f982cf4SFabien Sanglard 
558*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
559*3f982cf4SFabien Sanglard   Offer offer;
560*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
561*3f982cf4SFabien Sanglard }
562*3f982cf4SFabien Sanglard 
TEST(OfferTest,CanParseValidOffer)563*3f982cf4SFabien Sanglard TEST(OfferTest, CanParseValidOffer) {
564*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(kValidOffer);
565*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
566*3f982cf4SFabien Sanglard   Offer offer;
567*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
568*3f982cf4SFabien Sanglard 
569*3f982cf4SFabien Sanglard   ExpectEqualsValidOffer(offer);
570*3f982cf4SFabien Sanglard }
571*3f982cf4SFabien Sanglard 
TEST(OfferTest,ParseAndToJsonResultsInSameOffer)572*3f982cf4SFabien Sanglard TEST(OfferTest, ParseAndToJsonResultsInSameOffer) {
573*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(kValidOffer);
574*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
575*3f982cf4SFabien Sanglard   Offer offer;
576*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
577*3f982cf4SFabien Sanglard   ExpectEqualsValidOffer(offer);
578*3f982cf4SFabien Sanglard 
579*3f982cf4SFabien Sanglard   Offer reparsed_offer;
580*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &reparsed_offer).ok());
581*3f982cf4SFabien Sanglard   ExpectEqualsValidOffer(reparsed_offer);
582*3f982cf4SFabien Sanglard }
583*3f982cf4SFabien Sanglard 
584*3f982cf4SFabien Sanglard // We don't want to enforce that a given offer must have both audio and
585*3f982cf4SFabien Sanglard // video, so we don't assert on either.
TEST(OfferTest,IsValidWithMissingStreams)586*3f982cf4SFabien Sanglard TEST(OfferTest, IsValidWithMissingStreams) {
587*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(kValidOffer);
588*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
589*3f982cf4SFabien Sanglard   Offer offer;
590*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
591*3f982cf4SFabien Sanglard   ExpectEqualsValidOffer(offer);
592*3f982cf4SFabien Sanglard   const Offer valid_offer = std::move(offer);
593*3f982cf4SFabien Sanglard 
594*3f982cf4SFabien Sanglard   Offer missing_audio_streams = valid_offer;
595*3f982cf4SFabien Sanglard   missing_audio_streams.audio_streams.clear();
596*3f982cf4SFabien Sanglard   EXPECT_TRUE(missing_audio_streams.IsValid());
597*3f982cf4SFabien Sanglard 
598*3f982cf4SFabien Sanglard   Offer missing_video_streams = valid_offer;
599*3f982cf4SFabien Sanglard   missing_video_streams.audio_streams.clear();
600*3f982cf4SFabien Sanglard   EXPECT_TRUE(missing_video_streams.IsValid());
601*3f982cf4SFabien Sanglard }
602*3f982cf4SFabien Sanglard 
TEST(OfferTest,InvalidIfInvalidStreams)603*3f982cf4SFabien Sanglard TEST(OfferTest, InvalidIfInvalidStreams) {
604*3f982cf4SFabien Sanglard   ErrorOr<Json::Value> root = json::Parse(kValidOffer);
605*3f982cf4SFabien Sanglard   ASSERT_TRUE(root.is_value());
606*3f982cf4SFabien Sanglard   Offer offer;
607*3f982cf4SFabien Sanglard   EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok());
608*3f982cf4SFabien Sanglard   ExpectEqualsValidOffer(offer);
609*3f982cf4SFabien Sanglard 
610*3f982cf4SFabien Sanglard   Offer video_stream_invalid = offer;
611*3f982cf4SFabien Sanglard   video_stream_invalid.video_streams[0].max_frame_rate = SimpleFraction{1, 0};
612*3f982cf4SFabien Sanglard   EXPECT_FALSE(video_stream_invalid.IsValid());
613*3f982cf4SFabien Sanglard 
614*3f982cf4SFabien Sanglard   Offer audio_stream_invalid = offer;
615*3f982cf4SFabien Sanglard   video_stream_invalid.audio_streams[0].bit_rate = 0;
616*3f982cf4SFabien Sanglard   EXPECT_FALSE(video_stream_invalid.IsValid());
617*3f982cf4SFabien Sanglard }
618*3f982cf4SFabien Sanglard 
TEST(OfferTest,FailsIfUnencrypted)619*3f982cf4SFabien Sanglard TEST(OfferTest, FailsIfUnencrypted) {
620*3f982cf4SFabien Sanglard   // Video stream missing AES fields.
621*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
622*3f982cf4SFabien Sanglard     "castMode": "mirroring",
623*3f982cf4SFabien Sanglard     "supportedStreams": [{
624*3f982cf4SFabien Sanglard       "index": 2,
625*3f982cf4SFabien Sanglard       "type": "video_source",
626*3f982cf4SFabien Sanglard       "codecName": "vp8",
627*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
628*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
629*3f982cf4SFabien Sanglard       "ssrc": 19088743,
630*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
631*3f982cf4SFabien Sanglard        "resolutions": [],
632*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
633*3f982cf4SFabien Sanglard        "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
634*3f982cf4SFabien Sanglard     }]
635*3f982cf4SFabien Sanglard   })",
636*3f982cf4SFabien Sanglard                        Error::Code::kUnencryptedOffer);
637*3f982cf4SFabien Sanglard 
638*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
639*3f982cf4SFabien Sanglard     "castMode": "mirroring",
640*3f982cf4SFabien Sanglard     "supportedStreams": [{
641*3f982cf4SFabien Sanglard       "index": 2,
642*3f982cf4SFabien Sanglard       "type": "video_source",
643*3f982cf4SFabien Sanglard       "codecName": "vp8",
644*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
645*3f982cf4SFabien Sanglard       "rtpPayloadType": 100,
646*3f982cf4SFabien Sanglard       "ssrc": 19088743,
647*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
648*3f982cf4SFabien Sanglard        "resolutions": [],
649*3f982cf4SFabien Sanglard        "maxBitRate": 10000,
650*3f982cf4SFabien Sanglard        "aesKey": "51027e4e2347cbcb49d57ef10177aebc"
651*3f982cf4SFabien Sanglard     }]
652*3f982cf4SFabien Sanglard   })",
653*3f982cf4SFabien Sanglard                        Error::Code::kUnencryptedOffer);
654*3f982cf4SFabien Sanglard 
655*3f982cf4SFabien Sanglard   // Audio stream missing AES fields.
656*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
657*3f982cf4SFabien Sanglard     "castMode": "mirroring",
658*3f982cf4SFabien Sanglard     "supportedStreams": [{
659*3f982cf4SFabien Sanglard       "index": 2,
660*3f982cf4SFabien Sanglard       "type": "audio_source",
661*3f982cf4SFabien Sanglard       "codecName": "opus",
662*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
663*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
664*3f982cf4SFabien Sanglard       "ssrc": 19088743,
665*3f982cf4SFabien Sanglard       "bitRate": 124000,
666*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
667*3f982cf4SFabien Sanglard       "channels": 2,
668*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
669*3f982cf4SFabien Sanglard     }]
670*3f982cf4SFabien Sanglard   })",
671*3f982cf4SFabien Sanglard                        Error::Code::kUnencryptedOffer);
672*3f982cf4SFabien Sanglard 
673*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
674*3f982cf4SFabien Sanglard     "castMode": "mirroring",
675*3f982cf4SFabien Sanglard     "supportedStreams": [{
676*3f982cf4SFabien Sanglard       "index": 2,
677*3f982cf4SFabien Sanglard       "type": "audio_source",
678*3f982cf4SFabien Sanglard       "codecName": "opus",
679*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
680*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
681*3f982cf4SFabien Sanglard       "ssrc": 19088743,
682*3f982cf4SFabien Sanglard       "bitRate": 124000,
683*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
684*3f982cf4SFabien Sanglard       "channels": 2,
685*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347cbcb49d57ef10177aebc"
686*3f982cf4SFabien Sanglard     }]
687*3f982cf4SFabien Sanglard   })",
688*3f982cf4SFabien Sanglard                        Error::Code::kUnencryptedOffer);
689*3f982cf4SFabien Sanglard 
690*3f982cf4SFabien Sanglard   // And finally, fields provided but not properly formatted.
691*3f982cf4SFabien Sanglard   ExpectFailureOnParse(R"({
692*3f982cf4SFabien Sanglard     "castMode": "mirroring",
693*3f982cf4SFabien Sanglard     "supportedStreams": [{
694*3f982cf4SFabien Sanglard       "index": 2,
695*3f982cf4SFabien Sanglard       "type": "audio_source",
696*3f982cf4SFabien Sanglard       "codecName": "opus",
697*3f982cf4SFabien Sanglard       "rtpProfile": "cast",
698*3f982cf4SFabien Sanglard       "rtpPayloadType": 96,
699*3f982cf4SFabien Sanglard       "ssrc": 19088743,
700*3f982cf4SFabien Sanglard       "bitRate": 124000,
701*3f982cf4SFabien Sanglard       "timeBase": "1/48000",
702*3f982cf4SFabien Sanglard       "channels": 2,
703*3f982cf4SFabien Sanglard       "aesKey": "51027e4e2347$bcb49d57ef10177aebc",
704*3f982cf4SFabien Sanglard       "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1"
705*3f982cf4SFabien Sanglard     }]
706*3f982cf4SFabien Sanglard   })",
707*3f982cf4SFabien Sanglard                        Error::Code::kUnencryptedOffer);
708*3f982cf4SFabien Sanglard }
709*3f982cf4SFabien Sanglard 
710*3f982cf4SFabien Sanglard }  // namespace cast
711*3f982cf4SFabien Sanglard }  // namespace openscreen
712