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/answer_messages.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <chrono>
8*3f982cf4SFabien Sanglard #include <utility>
9*3f982cf4SFabien Sanglard
10*3f982cf4SFabien Sanglard #include "gmock/gmock.h"
11*3f982cf4SFabien Sanglard #include "gtest/gtest.h"
12*3f982cf4SFabien Sanglard #include "util/chrono_helpers.h"
13*3f982cf4SFabien Sanglard #include "util/json/json_serialization.h"
14*3f982cf4SFabien Sanglard
15*3f982cf4SFabien Sanglard namespace openscreen {
16*3f982cf4SFabien Sanglard namespace cast {
17*3f982cf4SFabien Sanglard
18*3f982cf4SFabien Sanglard namespace {
19*3f982cf4SFabien Sanglard
20*3f982cf4SFabien Sanglard using ::testing::ElementsAre;
21*3f982cf4SFabien Sanglard
22*3f982cf4SFabien Sanglard // NOTE: the castMode property has been removed from the specification. We leave
23*3f982cf4SFabien Sanglard // it here in the valid offer to ensure that its inclusion does not break
24*3f982cf4SFabien Sanglard // parsing.
25*3f982cf4SFabien Sanglard constexpr char kValidAnswerJson[] = R"({
26*3f982cf4SFabien Sanglard "castMode": "mirroring",
27*3f982cf4SFabien Sanglard "udpPort": 1234,
28*3f982cf4SFabien Sanglard "sendIndexes": [1, 3],
29*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222],
30*3f982cf4SFabien Sanglard "constraints": {
31*3f982cf4SFabien Sanglard "audio": {
32*3f982cf4SFabien Sanglard "maxSampleRate": 96000,
33*3f982cf4SFabien Sanglard "maxChannels": 5,
34*3f982cf4SFabien Sanglard "minBitRate": 32000,
35*3f982cf4SFabien Sanglard "maxBitRate": 320000,
36*3f982cf4SFabien Sanglard "maxDelay": 5000
37*3f982cf4SFabien Sanglard },
38*3f982cf4SFabien Sanglard "video": {
39*3f982cf4SFabien Sanglard "maxPixelsPerSecond": 62208000,
40*3f982cf4SFabien Sanglard "minResolution": {
41*3f982cf4SFabien Sanglard "width": 320,
42*3f982cf4SFabien Sanglard "height": 180,
43*3f982cf4SFabien Sanglard "frameRate": 0
44*3f982cf4SFabien Sanglard },
45*3f982cf4SFabien Sanglard "maxDimensions": {
46*3f982cf4SFabien Sanglard "width": 1920,
47*3f982cf4SFabien Sanglard "height": 1080,
48*3f982cf4SFabien Sanglard "frameRate": "60"
49*3f982cf4SFabien Sanglard },
50*3f982cf4SFabien Sanglard "minBitRate": 300000,
51*3f982cf4SFabien Sanglard "maxBitRate": 10000000,
52*3f982cf4SFabien Sanglard "maxDelay": 5000
53*3f982cf4SFabien Sanglard }
54*3f982cf4SFabien Sanglard },
55*3f982cf4SFabien Sanglard "display": {
56*3f982cf4SFabien Sanglard "dimensions": {
57*3f982cf4SFabien Sanglard "width": 1920,
58*3f982cf4SFabien Sanglard "height": 1080,
59*3f982cf4SFabien Sanglard "frameRate": "60000/1001"
60*3f982cf4SFabien Sanglard },
61*3f982cf4SFabien Sanglard "aspectRatio": "64:27",
62*3f982cf4SFabien Sanglard "scaling": "sender"
63*3f982cf4SFabien Sanglard },
64*3f982cf4SFabien Sanglard "receiverRtcpEventLog": [0, 1],
65*3f982cf4SFabien Sanglard "receiverRtcpDscp": [234, 567],
66*3f982cf4SFabien Sanglard "rtpExtensions": ["adaptive_playout_delay"]
67*3f982cf4SFabien Sanglard })";
68*3f982cf4SFabien Sanglard
69*3f982cf4SFabien Sanglard const Answer kValidAnswer{
70*3f982cf4SFabien Sanglard 1234, // udp_port
71*3f982cf4SFabien Sanglard std::vector<int>{1, 2, 3}, // send_indexes
72*3f982cf4SFabien Sanglard std::vector<Ssrc>{123, 456}, // ssrcs
73*3f982cf4SFabien Sanglard absl::optional<Constraints>(Constraints{
74*3f982cf4SFabien Sanglard AudioConstraints{
75*3f982cf4SFabien Sanglard 96000, // max_sample_rate
76*3f982cf4SFabien Sanglard 7, // max_channels
77*3f982cf4SFabien Sanglard 32000, // min_bit_rate
78*3f982cf4SFabien Sanglard 96000, // max_bit_rate
79*3f982cf4SFabien Sanglard milliseconds(2000) // max_delay
80*3f982cf4SFabien Sanglard }, // audio
81*3f982cf4SFabien Sanglard VideoConstraints{
82*3f982cf4SFabien Sanglard 40000.0, // max_pixels_per_second
83*3f982cf4SFabien Sanglard absl::optional<Dimensions>(
84*3f982cf4SFabien Sanglard Dimensions{320, 480, SimpleFraction{15000, 101}}),
85*3f982cf4SFabien Sanglard Dimensions{1920, 1080, SimpleFraction{288, 2}},
86*3f982cf4SFabien Sanglard 300000, // min_bit_rate
87*3f982cf4SFabien Sanglard 144000000, // max_bit_rate
88*3f982cf4SFabien Sanglard milliseconds(3000) // max_delay
89*3f982cf4SFabien Sanglard } // video
90*3f982cf4SFabien Sanglard }), // constraints
91*3f982cf4SFabien Sanglard absl::optional<DisplayDescription>(DisplayDescription{
92*3f982cf4SFabien Sanglard absl::optional<Dimensions>(Dimensions{640, 480, SimpleFraction{30, 1}}),
93*3f982cf4SFabien Sanglard absl::optional<AspectRatio>(AspectRatio{16, 9}), // aspect_ratio
94*3f982cf4SFabien Sanglard absl::optional<AspectRatioConstraint>(
95*3f982cf4SFabien Sanglard AspectRatioConstraint::kFixed), // scaling
96*3f982cf4SFabien Sanglard }),
97*3f982cf4SFabien Sanglard std::vector<int>{7, 8, 9}, // receiver_rtcp_event_log
98*3f982cf4SFabien Sanglard std::vector<int>{11, 12, 13}, // receiver_rtcp_dscp
99*3f982cf4SFabien Sanglard std::vector<std::string>{"foo", "bar"} // rtp_extensions
100*3f982cf4SFabien Sanglard };
101*3f982cf4SFabien Sanglard
102*3f982cf4SFabien Sanglard constexpr int kValidMaxPixelsPerSecond = 1920 * 1080 * 30;
103*3f982cf4SFabien Sanglard constexpr Dimensions kValidDimensions{1920, 1080, SimpleFraction{60, 1}};
104*3f982cf4SFabien Sanglard static const VideoConstraints kValidVideoConstraints{
105*3f982cf4SFabien Sanglard kValidMaxPixelsPerSecond, absl::optional<Dimensions>(kValidDimensions),
106*3f982cf4SFabien Sanglard kValidDimensions, 300 * 1000,
107*3f982cf4SFabien Sanglard 300 * 1000 * 1000, milliseconds(3000)};
108*3f982cf4SFabien Sanglard
109*3f982cf4SFabien Sanglard constexpr AudioConstraints kValidAudioConstraints{123, 456, 300, 9920,
110*3f982cf4SFabien Sanglard milliseconds(123)};
111*3f982cf4SFabien Sanglard
ExpectEqualsValidAnswerJson(const Answer & answer)112*3f982cf4SFabien Sanglard void ExpectEqualsValidAnswerJson(const Answer& answer) {
113*3f982cf4SFabien Sanglard EXPECT_EQ(1234, answer.udp_port);
114*3f982cf4SFabien Sanglard
115*3f982cf4SFabien Sanglard EXPECT_THAT(answer.send_indexes, ElementsAre(1, 3));
116*3f982cf4SFabien Sanglard EXPECT_THAT(answer.ssrcs, ElementsAre(1233324u, 2234222u));
117*3f982cf4SFabien Sanglard ASSERT_TRUE(answer.constraints.has_value());
118*3f982cf4SFabien Sanglard const AudioConstraints& audio = answer.constraints->audio;
119*3f982cf4SFabien Sanglard EXPECT_EQ(96000, audio.max_sample_rate);
120*3f982cf4SFabien Sanglard EXPECT_EQ(5, audio.max_channels);
121*3f982cf4SFabien Sanglard EXPECT_EQ(32000, audio.min_bit_rate);
122*3f982cf4SFabien Sanglard EXPECT_EQ(320000, audio.max_bit_rate);
123*3f982cf4SFabien Sanglard EXPECT_EQ(milliseconds{5000}, audio.max_delay);
124*3f982cf4SFabien Sanglard
125*3f982cf4SFabien Sanglard const VideoConstraints& video = answer.constraints->video;
126*3f982cf4SFabien Sanglard EXPECT_EQ(62208000, video.max_pixels_per_second);
127*3f982cf4SFabien Sanglard ASSERT_TRUE(video.min_resolution.has_value());
128*3f982cf4SFabien Sanglard EXPECT_EQ(320, video.min_resolution->width);
129*3f982cf4SFabien Sanglard EXPECT_EQ(180, video.min_resolution->height);
130*3f982cf4SFabien Sanglard EXPECT_EQ((SimpleFraction{0, 1}), video.min_resolution->frame_rate);
131*3f982cf4SFabien Sanglard EXPECT_EQ(1920, video.max_dimensions.width);
132*3f982cf4SFabien Sanglard EXPECT_EQ(1080, video.max_dimensions.height);
133*3f982cf4SFabien Sanglard EXPECT_EQ((SimpleFraction{60, 1}), video.max_dimensions.frame_rate);
134*3f982cf4SFabien Sanglard EXPECT_EQ(300000, video.min_bit_rate);
135*3f982cf4SFabien Sanglard EXPECT_EQ(10000000, video.max_bit_rate);
136*3f982cf4SFabien Sanglard EXPECT_EQ(milliseconds{5000}, video.max_delay);
137*3f982cf4SFabien Sanglard
138*3f982cf4SFabien Sanglard ASSERT_TRUE(answer.display.has_value());
139*3f982cf4SFabien Sanglard const DisplayDescription& display = answer.display.value();
140*3f982cf4SFabien Sanglard ASSERT_TRUE(display.dimensions.has_value());
141*3f982cf4SFabien Sanglard EXPECT_EQ(1920, display.dimensions->width);
142*3f982cf4SFabien Sanglard EXPECT_EQ(1080, display.dimensions->height);
143*3f982cf4SFabien Sanglard EXPECT_EQ((SimpleFraction{60000, 1001}), display.dimensions->frame_rate);
144*3f982cf4SFabien Sanglard EXPECT_EQ((AspectRatio{64, 27}), display.aspect_ratio.value());
145*3f982cf4SFabien Sanglard EXPECT_EQ(AspectRatioConstraint::kFixed,
146*3f982cf4SFabien Sanglard display.aspect_ratio_constraint.value());
147*3f982cf4SFabien Sanglard
148*3f982cf4SFabien Sanglard EXPECT_THAT(answer.receiver_rtcp_event_log, ElementsAre(0, 1));
149*3f982cf4SFabien Sanglard EXPECT_THAT(answer.receiver_rtcp_dscp, ElementsAre(234, 567));
150*3f982cf4SFabien Sanglard EXPECT_THAT(answer.rtp_extensions, ElementsAre("adaptive_playout_delay"));
151*3f982cf4SFabien Sanglard }
152*3f982cf4SFabien Sanglard
ExpectFailureOnParse(absl::string_view raw_json)153*3f982cf4SFabien Sanglard void ExpectFailureOnParse(absl::string_view raw_json) {
154*3f982cf4SFabien Sanglard ErrorOr<Json::Value> root = json::Parse(raw_json);
155*3f982cf4SFabien Sanglard // Must be a valid JSON object, but not a valid answer.
156*3f982cf4SFabien Sanglard ASSERT_TRUE(root.is_value());
157*3f982cf4SFabien Sanglard
158*3f982cf4SFabien Sanglard Answer answer;
159*3f982cf4SFabien Sanglard EXPECT_FALSE(Answer::TryParse(std::move(root.value()), &answer));
160*3f982cf4SFabien Sanglard EXPECT_FALSE(answer.IsValid());
161*3f982cf4SFabien Sanglard }
162*3f982cf4SFabien Sanglard
163*3f982cf4SFabien Sanglard // Functions that use ASSERT_* must return void, so we use an out parameter
164*3f982cf4SFabien Sanglard // here instead of returning.
ExpectSuccessOnParse(absl::string_view raw_json,Answer * out=nullptr)165*3f982cf4SFabien Sanglard void ExpectSuccessOnParse(absl::string_view raw_json, Answer* out = nullptr) {
166*3f982cf4SFabien Sanglard ErrorOr<Json::Value> root = json::Parse(raw_json);
167*3f982cf4SFabien Sanglard // Must be a valid JSON object, but not a valid answer.
168*3f982cf4SFabien Sanglard ASSERT_TRUE(root.is_value());
169*3f982cf4SFabien Sanglard
170*3f982cf4SFabien Sanglard Answer answer;
171*3f982cf4SFabien Sanglard ASSERT_TRUE(Answer::TryParse(std::move(root.value()), &answer));
172*3f982cf4SFabien Sanglard EXPECT_TRUE(answer.IsValid());
173*3f982cf4SFabien Sanglard if (out) {
174*3f982cf4SFabien Sanglard *out = std::move(answer);
175*3f982cf4SFabien Sanglard }
176*3f982cf4SFabien Sanglard }
177*3f982cf4SFabien Sanglard
178*3f982cf4SFabien Sanglard } // anonymous namespace
179*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ProperlyPopulatedAnswerSerializesProperly)180*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ProperlyPopulatedAnswerSerializesProperly) {
181*3f982cf4SFabien Sanglard ASSERT_TRUE(kValidAnswer.IsValid());
182*3f982cf4SFabien Sanglard Json::Value root = kValidAnswer.ToJson();
183*3f982cf4SFabien Sanglard EXPECT_EQ(root["udpPort"], 1234);
184*3f982cf4SFabien Sanglard
185*3f982cf4SFabien Sanglard Json::Value sendIndexes = std::move(root["sendIndexes"]);
186*3f982cf4SFabien Sanglard EXPECT_EQ(sendIndexes.type(), Json::ValueType::arrayValue);
187*3f982cf4SFabien Sanglard EXPECT_EQ(sendIndexes[0], 1);
188*3f982cf4SFabien Sanglard EXPECT_EQ(sendIndexes[1], 2);
189*3f982cf4SFabien Sanglard EXPECT_EQ(sendIndexes[2], 3);
190*3f982cf4SFabien Sanglard
191*3f982cf4SFabien Sanglard Json::Value ssrcs = std::move(root["ssrcs"]);
192*3f982cf4SFabien Sanglard EXPECT_EQ(ssrcs.type(), Json::ValueType::arrayValue);
193*3f982cf4SFabien Sanglard EXPECT_EQ(ssrcs[0], 123u);
194*3f982cf4SFabien Sanglard EXPECT_EQ(ssrcs[1], 456u);
195*3f982cf4SFabien Sanglard
196*3f982cf4SFabien Sanglard Json::Value constraints = std::move(root["constraints"]);
197*3f982cf4SFabien Sanglard Json::Value audio = std::move(constraints["audio"]);
198*3f982cf4SFabien Sanglard EXPECT_EQ(audio.type(), Json::ValueType::objectValue);
199*3f982cf4SFabien Sanglard EXPECT_EQ(audio["maxSampleRate"], 96000);
200*3f982cf4SFabien Sanglard EXPECT_EQ(audio["maxChannels"], 7);
201*3f982cf4SFabien Sanglard EXPECT_EQ(audio["minBitRate"], 32000);
202*3f982cf4SFabien Sanglard EXPECT_EQ(audio["maxBitRate"], 96000);
203*3f982cf4SFabien Sanglard EXPECT_EQ(audio["maxDelay"], 2000);
204*3f982cf4SFabien Sanglard
205*3f982cf4SFabien Sanglard Json::Value video = std::move(constraints["video"]);
206*3f982cf4SFabien Sanglard EXPECT_EQ(video.type(), Json::ValueType::objectValue);
207*3f982cf4SFabien Sanglard EXPECT_EQ(video["maxPixelsPerSecond"], 40000.0);
208*3f982cf4SFabien Sanglard EXPECT_EQ(video["minBitRate"], 300000);
209*3f982cf4SFabien Sanglard EXPECT_EQ(video["maxBitRate"], 144000000);
210*3f982cf4SFabien Sanglard EXPECT_EQ(video["maxDelay"], 3000);
211*3f982cf4SFabien Sanglard
212*3f982cf4SFabien Sanglard Json::Value min_resolution = std::move(video["minResolution"]);
213*3f982cf4SFabien Sanglard EXPECT_EQ(min_resolution.type(), Json::ValueType::objectValue);
214*3f982cf4SFabien Sanglard EXPECT_EQ(min_resolution["width"], 320);
215*3f982cf4SFabien Sanglard EXPECT_EQ(min_resolution["height"], 480);
216*3f982cf4SFabien Sanglard EXPECT_EQ(min_resolution["frameRate"], "15000/101");
217*3f982cf4SFabien Sanglard
218*3f982cf4SFabien Sanglard Json::Value max_dimensions = std::move(video["maxDimensions"]);
219*3f982cf4SFabien Sanglard EXPECT_EQ(max_dimensions.type(), Json::ValueType::objectValue);
220*3f982cf4SFabien Sanglard EXPECT_EQ(max_dimensions["width"], 1920);
221*3f982cf4SFabien Sanglard EXPECT_EQ(max_dimensions["height"], 1080);
222*3f982cf4SFabien Sanglard EXPECT_EQ(max_dimensions["frameRate"], "288/2");
223*3f982cf4SFabien Sanglard
224*3f982cf4SFabien Sanglard Json::Value display = std::move(root["display"]);
225*3f982cf4SFabien Sanglard EXPECT_EQ(display.type(), Json::ValueType::objectValue);
226*3f982cf4SFabien Sanglard EXPECT_EQ(display["aspectRatio"], "16:9");
227*3f982cf4SFabien Sanglard EXPECT_EQ(display["scaling"], "sender");
228*3f982cf4SFabien Sanglard
229*3f982cf4SFabien Sanglard Json::Value dimensions = std::move(display["dimensions"]);
230*3f982cf4SFabien Sanglard EXPECT_EQ(dimensions.type(), Json::ValueType::objectValue);
231*3f982cf4SFabien Sanglard EXPECT_EQ(dimensions["width"], 640);
232*3f982cf4SFabien Sanglard EXPECT_EQ(dimensions["height"], 480);
233*3f982cf4SFabien Sanglard EXPECT_EQ(dimensions["frameRate"], "30");
234*3f982cf4SFabien Sanglard
235*3f982cf4SFabien Sanglard Json::Value receiver_rtcp_event_log = std::move(root["receiverRtcpEventLog"]);
236*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_event_log.type(), Json::ValueType::arrayValue);
237*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_event_log[0], 7);
238*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_event_log[1], 8);
239*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_event_log[2], 9);
240*3f982cf4SFabien Sanglard
241*3f982cf4SFabien Sanglard Json::Value receiver_rtcp_dscp = std::move(root["receiverRtcpDscp"]);
242*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_dscp.type(), Json::ValueType::arrayValue);
243*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_dscp[0], 11);
244*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_dscp[1], 12);
245*3f982cf4SFabien Sanglard EXPECT_EQ(receiver_rtcp_dscp[2], 13);
246*3f982cf4SFabien Sanglard
247*3f982cf4SFabien Sanglard Json::Value rtp_extensions = std::move(root["rtpExtensions"]);
248*3f982cf4SFabien Sanglard EXPECT_EQ(rtp_extensions.type(), Json::ValueType::arrayValue);
249*3f982cf4SFabien Sanglard EXPECT_EQ(rtp_extensions[0], "foo");
250*3f982cf4SFabien Sanglard EXPECT_EQ(rtp_extensions[1], "bar");
251*3f982cf4SFabien Sanglard }
252*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,EmptyArraysOmitted)253*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, EmptyArraysOmitted) {
254*3f982cf4SFabien Sanglard Answer missing_event_log = kValidAnswer;
255*3f982cf4SFabien Sanglard missing_event_log.receiver_rtcp_event_log.clear();
256*3f982cf4SFabien Sanglard ASSERT_TRUE(missing_event_log.IsValid());
257*3f982cf4SFabien Sanglard Json::Value root = missing_event_log.ToJson();
258*3f982cf4SFabien Sanglard EXPECT_FALSE(root["receiverRtcpEventLog"]);
259*3f982cf4SFabien Sanglard
260*3f982cf4SFabien Sanglard Answer missing_rtcp_dscp = kValidAnswer;
261*3f982cf4SFabien Sanglard missing_rtcp_dscp.receiver_rtcp_dscp.clear();
262*3f982cf4SFabien Sanglard ASSERT_TRUE(missing_rtcp_dscp.IsValid());
263*3f982cf4SFabien Sanglard root = missing_rtcp_dscp.ToJson();
264*3f982cf4SFabien Sanglard EXPECT_FALSE(root["receiverRtcpDscp"]);
265*3f982cf4SFabien Sanglard
266*3f982cf4SFabien Sanglard Answer missing_extensions = kValidAnswer;
267*3f982cf4SFabien Sanglard missing_extensions.rtp_extensions.clear();
268*3f982cf4SFabien Sanglard ASSERT_TRUE(missing_extensions.IsValid());
269*3f982cf4SFabien Sanglard root = missing_extensions.ToJson();
270*3f982cf4SFabien Sanglard EXPECT_FALSE(root["rtpExtensions"]);
271*3f982cf4SFabien Sanglard }
272*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,InvalidDimensionsCauseInvalid)273*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, InvalidDimensionsCauseInvalid) {
274*3f982cf4SFabien Sanglard Answer invalid_dimensions = kValidAnswer;
275*3f982cf4SFabien Sanglard invalid_dimensions.display->dimensions->width = -1;
276*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_dimensions.IsValid());
277*3f982cf4SFabien Sanglard }
278*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,InvalidAudioConstraintsCauseError)279*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, InvalidAudioConstraintsCauseError) {
280*3f982cf4SFabien Sanglard Answer invalid_audio = kValidAnswer;
281*3f982cf4SFabien Sanglard invalid_audio.constraints->audio.max_bit_rate =
282*3f982cf4SFabien Sanglard invalid_audio.constraints->audio.min_bit_rate - 1;
283*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_audio.IsValid());
284*3f982cf4SFabien Sanglard }
285*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,InvalidVideoConstraintsCauseError)286*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, InvalidVideoConstraintsCauseError) {
287*3f982cf4SFabien Sanglard Answer invalid_video = kValidAnswer;
288*3f982cf4SFabien Sanglard invalid_video.constraints->video.max_pixels_per_second = -1.0;
289*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_video.IsValid());
290*3f982cf4SFabien Sanglard }
291*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,InvalidDisplayDescriptionsCauseError)292*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, InvalidDisplayDescriptionsCauseError) {
293*3f982cf4SFabien Sanglard Answer invalid_display = kValidAnswer;
294*3f982cf4SFabien Sanglard invalid_display.display->aspect_ratio = {0, 0};
295*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_display.IsValid());
296*3f982cf4SFabien Sanglard }
297*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,InvalidUdpPortsCauseError)298*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, InvalidUdpPortsCauseError) {
299*3f982cf4SFabien Sanglard Answer invalid_port = kValidAnswer;
300*3f982cf4SFabien Sanglard invalid_port.udp_port = 65536;
301*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_port.IsValid());
302*3f982cf4SFabien Sanglard }
303*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,CanParseValidAnswerJson)304*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, CanParseValidAnswerJson) {
305*3f982cf4SFabien Sanglard Answer answer;
306*3f982cf4SFabien Sanglard ExpectSuccessOnParse(kValidAnswerJson, &answer);
307*3f982cf4SFabien Sanglard ExpectEqualsValidAnswerJson(answer);
308*3f982cf4SFabien Sanglard }
309*3f982cf4SFabien Sanglard
310*3f982cf4SFabien Sanglard // In practice, the rtpExtensions, receiverRtcpDscp, and receiverRtcpEventLog
311*3f982cf4SFabien Sanglard // fields may be missing from some receivers. We handle this case by treating
312*3f982cf4SFabien Sanglard // them as empty.
TEST(AnswerMessagesTest,SucceedsWithMissingRtpFields)313*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, SucceedsWithMissingRtpFields) {
314*3f982cf4SFabien Sanglard ExpectSuccessOnParse(R"({
315*3f982cf4SFabien Sanglard "udpPort": 1234,
316*3f982cf4SFabien Sanglard "sendIndexes": [1, 3],
317*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222]
318*3f982cf4SFabien Sanglard })");
319*3f982cf4SFabien Sanglard }
320*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ErrorOnEmptyAnswer)321*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ErrorOnEmptyAnswer) {
322*3f982cf4SFabien Sanglard ExpectFailureOnParse("{}");
323*3f982cf4SFabien Sanglard }
324*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ErrorOnMissingUdpPort)325*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ErrorOnMissingUdpPort) {
326*3f982cf4SFabien Sanglard ExpectFailureOnParse(R"({
327*3f982cf4SFabien Sanglard "sendIndexes": [1, 3],
328*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222]
329*3f982cf4SFabien Sanglard })");
330*3f982cf4SFabien Sanglard }
331*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ErrorOnMissingSsrcs)332*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ErrorOnMissingSsrcs) {
333*3f982cf4SFabien Sanglard ExpectFailureOnParse(R"({
334*3f982cf4SFabien Sanglard "udpPort": 1234,
335*3f982cf4SFabien Sanglard "sendIndexes": [1, 3]
336*3f982cf4SFabien Sanglard })");
337*3f982cf4SFabien Sanglard }
338*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ErrorOnMissingSendIndexes)339*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ErrorOnMissingSendIndexes) {
340*3f982cf4SFabien Sanglard ExpectFailureOnParse(R"({
341*3f982cf4SFabien Sanglard "udpPort": 1234,
342*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222]
343*3f982cf4SFabien Sanglard })");
344*3f982cf4SFabien Sanglard }
345*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,AllowsReceiverSideScaling)346*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, AllowsReceiverSideScaling) {
347*3f982cf4SFabien Sanglard Answer answer;
348*3f982cf4SFabien Sanglard ExpectSuccessOnParse(R"({
349*3f982cf4SFabien Sanglard "udpPort": 1234,
350*3f982cf4SFabien Sanglard "sendIndexes": [1, 3],
351*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222],
352*3f982cf4SFabien Sanglard "display": {
353*3f982cf4SFabien Sanglard "dimensions": {
354*3f982cf4SFabien Sanglard "width": 1920,
355*3f982cf4SFabien Sanglard "height": 1080,
356*3f982cf4SFabien Sanglard "frameRate": "60000/1001"
357*3f982cf4SFabien Sanglard },
358*3f982cf4SFabien Sanglard "aspectRatio": "64:27",
359*3f982cf4SFabien Sanglard "scaling": "receiver"
360*3f982cf4SFabien Sanglard }
361*3f982cf4SFabien Sanglard })",
362*3f982cf4SFabien Sanglard &answer);
363*3f982cf4SFabien Sanglard ASSERT_TRUE(answer.display.has_value());
364*3f982cf4SFabien Sanglard EXPECT_EQ(answer.display->aspect_ratio_constraint.value(),
365*3f982cf4SFabien Sanglard AspectRatioConstraint::kVariable);
366*3f982cf4SFabien Sanglard }
367*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,AssumesMinBitRateIfOmitted)368*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, AssumesMinBitRateIfOmitted) {
369*3f982cf4SFabien Sanglard Answer answer;
370*3f982cf4SFabien Sanglard ExpectSuccessOnParse(R"({
371*3f982cf4SFabien Sanglard "udpPort": 1234,
372*3f982cf4SFabien Sanglard "sendIndexes": [1, 3],
373*3f982cf4SFabien Sanglard "ssrcs": [1233324, 2234222],
374*3f982cf4SFabien Sanglard "constraints": {
375*3f982cf4SFabien Sanglard "audio": {
376*3f982cf4SFabien Sanglard "maxSampleRate": 96000,
377*3f982cf4SFabien Sanglard "maxChannels": 5,
378*3f982cf4SFabien Sanglard "maxBitRate": 320000,
379*3f982cf4SFabien Sanglard "maxDelay": 5000
380*3f982cf4SFabien Sanglard },
381*3f982cf4SFabien Sanglard "video": {
382*3f982cf4SFabien Sanglard "maxPixelsPerSecond": 62208000,
383*3f982cf4SFabien Sanglard "maxDimensions": {
384*3f982cf4SFabien Sanglard "width": 1920,
385*3f982cf4SFabien Sanglard "height": 1080,
386*3f982cf4SFabien Sanglard "frameRate": "60"
387*3f982cf4SFabien Sanglard },
388*3f982cf4SFabien Sanglard "maxBitRate": 10000000,
389*3f982cf4SFabien Sanglard "maxDelay": 5000
390*3f982cf4SFabien Sanglard }
391*3f982cf4SFabien Sanglard }
392*3f982cf4SFabien Sanglard })",
393*3f982cf4SFabien Sanglard &answer);
394*3f982cf4SFabien Sanglard
395*3f982cf4SFabien Sanglard EXPECT_EQ(32000, answer.constraints->audio.min_bit_rate);
396*3f982cf4SFabien Sanglard EXPECT_EQ(300000, answer.constraints->video.min_bit_rate);
397*3f982cf4SFabien Sanglard }
398*3f982cf4SFabien Sanglard
399*3f982cf4SFabien Sanglard // Instead of testing all possible json parsing options for validity, we
400*3f982cf4SFabien Sanglard // can instead directly test the IsValid() methods.
TEST(AnswerMessagesTest,AudioConstraintsIsValid)401*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, AudioConstraintsIsValid) {
402*3f982cf4SFabien Sanglard constexpr AudioConstraints kInvalidSampleRate{0, 456, 300, 9920,
403*3f982cf4SFabien Sanglard milliseconds(123)};
404*3f982cf4SFabien Sanglard constexpr AudioConstraints kInvalidMaxChannels{123, 0, 300, 9920,
405*3f982cf4SFabien Sanglard milliseconds(123)};
406*3f982cf4SFabien Sanglard constexpr AudioConstraints kInvalidMinBitRate{123, 456, 0, 9920,
407*3f982cf4SFabien Sanglard milliseconds(123)};
408*3f982cf4SFabien Sanglard constexpr AudioConstraints kInvalidMaxBitRate{123, 456, 300, 0,
409*3f982cf4SFabien Sanglard milliseconds(123)};
410*3f982cf4SFabien Sanglard constexpr AudioConstraints kInvalidMaxDelay{123, 456, 300, 0,
411*3f982cf4SFabien Sanglard milliseconds(0)};
412*3f982cf4SFabien Sanglard
413*3f982cf4SFabien Sanglard EXPECT_TRUE(kValidAudioConstraints.IsValid());
414*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidSampleRate.IsValid());
415*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidMaxChannels.IsValid());
416*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidMinBitRate.IsValid());
417*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidMaxBitRate.IsValid());
418*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidMaxDelay.IsValid());
419*3f982cf4SFabien Sanglard }
420*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,DimensionsIsValid)421*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, DimensionsIsValid) {
422*3f982cf4SFabien Sanglard // NOTE: in some cases (such as min dimensions) a frame rate of zero is valid.
423*3f982cf4SFabien Sanglard constexpr Dimensions kValidZeroFrameRate{1920, 1080, SimpleFraction{0, 60}};
424*3f982cf4SFabien Sanglard constexpr Dimensions kInvalidWidth{0, 1080, SimpleFraction{60, 1}};
425*3f982cf4SFabien Sanglard constexpr Dimensions kInvalidHeight{1920, 0, SimpleFraction{60, 1}};
426*3f982cf4SFabien Sanglard constexpr Dimensions kInvalidFrameRateZeroDenominator{1920, 1080,
427*3f982cf4SFabien Sanglard SimpleFraction{60, 0}};
428*3f982cf4SFabien Sanglard constexpr Dimensions kInvalidFrameRateNegativeNumerator{
429*3f982cf4SFabien Sanglard 1920, 1080, SimpleFraction{-1, 30}};
430*3f982cf4SFabien Sanglard constexpr Dimensions kInvalidFrameRateNegativeDenominator{
431*3f982cf4SFabien Sanglard 1920, 1080, SimpleFraction{30, -1}};
432*3f982cf4SFabien Sanglard
433*3f982cf4SFabien Sanglard EXPECT_TRUE(kValidDimensions.IsValid());
434*3f982cf4SFabien Sanglard EXPECT_TRUE(kValidZeroFrameRate.IsValid());
435*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidWidth.IsValid());
436*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidHeight.IsValid());
437*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidFrameRateZeroDenominator.IsValid());
438*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidFrameRateNegativeNumerator.IsValid());
439*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidFrameRateNegativeDenominator.IsValid());
440*3f982cf4SFabien Sanglard }
441*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,VideoConstraintsIsValid)442*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, VideoConstraintsIsValid) {
443*3f982cf4SFabien Sanglard VideoConstraints invalid_max_pixels_per_second = kValidVideoConstraints;
444*3f982cf4SFabien Sanglard invalid_max_pixels_per_second.max_pixels_per_second = 0;
445*3f982cf4SFabien Sanglard
446*3f982cf4SFabien Sanglard VideoConstraints invalid_min_resolution = kValidVideoConstraints;
447*3f982cf4SFabien Sanglard invalid_min_resolution.min_resolution->width = 0;
448*3f982cf4SFabien Sanglard
449*3f982cf4SFabien Sanglard VideoConstraints invalid_max_dimensions = kValidVideoConstraints;
450*3f982cf4SFabien Sanglard invalid_max_dimensions.max_dimensions.height = 0;
451*3f982cf4SFabien Sanglard
452*3f982cf4SFabien Sanglard VideoConstraints invalid_min_bit_rate = kValidVideoConstraints;
453*3f982cf4SFabien Sanglard invalid_min_bit_rate.min_bit_rate = 0;
454*3f982cf4SFabien Sanglard
455*3f982cf4SFabien Sanglard VideoConstraints invalid_max_bit_rate = kValidVideoConstraints;
456*3f982cf4SFabien Sanglard invalid_max_bit_rate.max_bit_rate = invalid_max_bit_rate.min_bit_rate - 1;
457*3f982cf4SFabien Sanglard
458*3f982cf4SFabien Sanglard VideoConstraints invalid_max_delay = kValidVideoConstraints;
459*3f982cf4SFabien Sanglard invalid_max_delay.max_delay = milliseconds(0);
460*3f982cf4SFabien Sanglard
461*3f982cf4SFabien Sanglard EXPECT_TRUE(kValidVideoConstraints.IsValid());
462*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_max_pixels_per_second.IsValid());
463*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_min_resolution.IsValid());
464*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_max_dimensions.IsValid());
465*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_min_bit_rate.IsValid());
466*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_max_bit_rate.IsValid());
467*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_max_delay.IsValid());
468*3f982cf4SFabien Sanglard }
469*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,ConstraintsIsValid)470*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, ConstraintsIsValid) {
471*3f982cf4SFabien Sanglard VideoConstraints invalid_video_constraints = kValidVideoConstraints;
472*3f982cf4SFabien Sanglard invalid_video_constraints.max_pixels_per_second = 0;
473*3f982cf4SFabien Sanglard
474*3f982cf4SFabien Sanglard AudioConstraints invalid_audio_constraints = kValidAudioConstraints;
475*3f982cf4SFabien Sanglard invalid_audio_constraints.max_bit_rate = 0;
476*3f982cf4SFabien Sanglard
477*3f982cf4SFabien Sanglard const Constraints valid{kValidAudioConstraints, kValidVideoConstraints};
478*3f982cf4SFabien Sanglard const Constraints invalid_audio{kValidAudioConstraints,
479*3f982cf4SFabien Sanglard invalid_video_constraints};
480*3f982cf4SFabien Sanglard const Constraints invalid_video{invalid_audio_constraints,
481*3f982cf4SFabien Sanglard kValidVideoConstraints};
482*3f982cf4SFabien Sanglard
483*3f982cf4SFabien Sanglard EXPECT_TRUE(valid.IsValid());
484*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_audio.IsValid());
485*3f982cf4SFabien Sanglard EXPECT_FALSE(invalid_video.IsValid());
486*3f982cf4SFabien Sanglard }
487*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,AspectRatioIsValid)488*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, AspectRatioIsValid) {
489*3f982cf4SFabien Sanglard constexpr AspectRatio kValid{16, 9};
490*3f982cf4SFabien Sanglard constexpr AspectRatio kInvalidWidth{0, 9};
491*3f982cf4SFabien Sanglard constexpr AspectRatio kInvalidHeight{16, 0};
492*3f982cf4SFabien Sanglard
493*3f982cf4SFabien Sanglard EXPECT_TRUE(kValid.IsValid());
494*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidWidth.IsValid());
495*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidHeight.IsValid());
496*3f982cf4SFabien Sanglard }
497*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,AspectRatioTryParse)498*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, AspectRatioTryParse) {
499*3f982cf4SFabien Sanglard const Json::Value kValid = "16:9";
500*3f982cf4SFabien Sanglard const Json::Value kWrongDelimiter = "16-9";
501*3f982cf4SFabien Sanglard const Json::Value kTooManyFields = "16:9:3";
502*3f982cf4SFabien Sanglard const Json::Value kTooFewFields = "1:";
503*3f982cf4SFabien Sanglard const Json::Value kNoDelimiter = "12345";
504*3f982cf4SFabien Sanglard const Json::Value kNegativeWidth = "-123:2345";
505*3f982cf4SFabien Sanglard const Json::Value kNegativeHeight = "22:-7";
506*3f982cf4SFabien Sanglard const Json::Value kNegativeBoth = "22:-7";
507*3f982cf4SFabien Sanglard const Json::Value kNonNumberWidth = "twenty2#:9";
508*3f982cf4SFabien Sanglard const Json::Value kNonNumberHeight = "2:thirty";
509*3f982cf4SFabien Sanglard const Json::Value kZeroWidth = "0:9";
510*3f982cf4SFabien Sanglard const Json::Value kZeroHeight = "16:0";
511*3f982cf4SFabien Sanglard
512*3f982cf4SFabien Sanglard AspectRatio out;
513*3f982cf4SFabien Sanglard EXPECT_TRUE(AspectRatio::TryParse(kValid, &out));
514*3f982cf4SFabien Sanglard EXPECT_EQ(out.width, 16);
515*3f982cf4SFabien Sanglard EXPECT_EQ(out.height, 9);
516*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kWrongDelimiter, &out));
517*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kTooManyFields, &out));
518*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kTooFewFields, &out));
519*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kWrongDelimiter, &out));
520*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNoDelimiter, &out));
521*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNegativeWidth, &out));
522*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNegativeHeight, &out));
523*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNegativeBoth, &out));
524*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNonNumberWidth, &out));
525*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kNonNumberHeight, &out));
526*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kZeroWidth, &out));
527*3f982cf4SFabien Sanglard EXPECT_FALSE(AspectRatio::TryParse(kZeroHeight, &out));
528*3f982cf4SFabien Sanglard }
529*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,DisplayDescriptionTryParse)530*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, DisplayDescriptionTryParse) {
531*3f982cf4SFabien Sanglard Json::Value valid_scaling;
532*3f982cf4SFabien Sanglard valid_scaling["scaling"] = "receiver";
533*3f982cf4SFabien Sanglard Json::Value invalid_scaling;
534*3f982cf4SFabien Sanglard invalid_scaling["scaling"] = "embedder";
535*3f982cf4SFabien Sanglard Json::Value invalid_scaling_valid_ratio;
536*3f982cf4SFabien Sanglard invalid_scaling_valid_ratio["scaling"] = "embedder";
537*3f982cf4SFabien Sanglard invalid_scaling_valid_ratio["aspectRatio"] = "16:9";
538*3f982cf4SFabien Sanglard
539*3f982cf4SFabien Sanglard Json::Value dimensions;
540*3f982cf4SFabien Sanglard dimensions["width"] = 1920;
541*3f982cf4SFabien Sanglard dimensions["height"] = 1080;
542*3f982cf4SFabien Sanglard dimensions["frameRate"] = "30";
543*3f982cf4SFabien Sanglard Json::Value valid_dimensions;
544*3f982cf4SFabien Sanglard valid_dimensions["dimensions"] = dimensions;
545*3f982cf4SFabien Sanglard
546*3f982cf4SFabien Sanglard Json::Value dimensions_invalid = dimensions;
547*3f982cf4SFabien Sanglard dimensions_invalid["frameRate"] = "infinity";
548*3f982cf4SFabien Sanglard Json::Value invalid_dimensions;
549*3f982cf4SFabien Sanglard invalid_dimensions["dimensions"] = dimensions_invalid;
550*3f982cf4SFabien Sanglard
551*3f982cf4SFabien Sanglard Json::Value aspect_ratio_and_constraint;
552*3f982cf4SFabien Sanglard aspect_ratio_and_constraint["scaling"] = "sender";
553*3f982cf4SFabien Sanglard aspect_ratio_and_constraint["aspectRatio"] = "4:3";
554*3f982cf4SFabien Sanglard
555*3f982cf4SFabien Sanglard DisplayDescription out;
556*3f982cf4SFabien Sanglard ASSERT_TRUE(DisplayDescription::TryParse(valid_scaling, &out));
557*3f982cf4SFabien Sanglard ASSERT_TRUE(out.aspect_ratio_constraint.has_value());
558*3f982cf4SFabien Sanglard EXPECT_EQ(out.aspect_ratio_constraint.value(),
559*3f982cf4SFabien Sanglard AspectRatioConstraint::kVariable);
560*3f982cf4SFabien Sanglard
561*3f982cf4SFabien Sanglard EXPECT_FALSE(DisplayDescription::TryParse(invalid_scaling, &out));
562*3f982cf4SFabien Sanglard EXPECT_TRUE(DisplayDescription::TryParse(invalid_scaling_valid_ratio, &out));
563*3f982cf4SFabien Sanglard
564*3f982cf4SFabien Sanglard ASSERT_TRUE(DisplayDescription::TryParse(valid_dimensions, &out));
565*3f982cf4SFabien Sanglard ASSERT_TRUE(out.dimensions.has_value());
566*3f982cf4SFabien Sanglard EXPECT_EQ(1920, out.dimensions->width);
567*3f982cf4SFabien Sanglard EXPECT_EQ(1080, out.dimensions->height);
568*3f982cf4SFabien Sanglard EXPECT_EQ((SimpleFraction{30, 1}), out.dimensions->frame_rate);
569*3f982cf4SFabien Sanglard
570*3f982cf4SFabien Sanglard EXPECT_FALSE(DisplayDescription::TryParse(invalid_dimensions, &out));
571*3f982cf4SFabien Sanglard
572*3f982cf4SFabien Sanglard ASSERT_TRUE(DisplayDescription::TryParse(aspect_ratio_and_constraint, &out));
573*3f982cf4SFabien Sanglard EXPECT_EQ(AspectRatioConstraint::kFixed, out.aspect_ratio_constraint.value());
574*3f982cf4SFabien Sanglard }
575*3f982cf4SFabien Sanglard
TEST(AnswerMessagesTest,DisplayDescriptionIsValid)576*3f982cf4SFabien Sanglard TEST(AnswerMessagesTest, DisplayDescriptionIsValid) {
577*3f982cf4SFabien Sanglard const DisplayDescription kInvalidEmptyDescription{
578*3f982cf4SFabien Sanglard absl::optional<Dimensions>{}, absl::optional<AspectRatio>{},
579*3f982cf4SFabien Sanglard absl::optional<AspectRatioConstraint>{}};
580*3f982cf4SFabien Sanglard
581*3f982cf4SFabien Sanglard DisplayDescription has_valid_dimensions = kInvalidEmptyDescription;
582*3f982cf4SFabien Sanglard has_valid_dimensions.dimensions =
583*3f982cf4SFabien Sanglard absl::optional<Dimensions>(kValidDimensions);
584*3f982cf4SFabien Sanglard
585*3f982cf4SFabien Sanglard DisplayDescription has_invalid_dimensions = kInvalidEmptyDescription;
586*3f982cf4SFabien Sanglard has_invalid_dimensions.dimensions =
587*3f982cf4SFabien Sanglard absl::optional<Dimensions>(kValidDimensions);
588*3f982cf4SFabien Sanglard has_invalid_dimensions.dimensions->width = 0;
589*3f982cf4SFabien Sanglard
590*3f982cf4SFabien Sanglard DisplayDescription has_aspect_ratio = kInvalidEmptyDescription;
591*3f982cf4SFabien Sanglard has_aspect_ratio.aspect_ratio =
592*3f982cf4SFabien Sanglard absl::optional<AspectRatio>{AspectRatio{16, 9}};
593*3f982cf4SFabien Sanglard
594*3f982cf4SFabien Sanglard DisplayDescription has_invalid_aspect_ratio = kInvalidEmptyDescription;
595*3f982cf4SFabien Sanglard has_invalid_aspect_ratio.aspect_ratio =
596*3f982cf4SFabien Sanglard absl::optional<AspectRatio>{AspectRatio{0, 20}};
597*3f982cf4SFabien Sanglard
598*3f982cf4SFabien Sanglard DisplayDescription has_aspect_ratio_constraint = kInvalidEmptyDescription;
599*3f982cf4SFabien Sanglard has_aspect_ratio_constraint.aspect_ratio_constraint =
600*3f982cf4SFabien Sanglard absl::optional<AspectRatioConstraint>(AspectRatioConstraint::kFixed);
601*3f982cf4SFabien Sanglard
602*3f982cf4SFabien Sanglard DisplayDescription has_constraint_and_dimensions =
603*3f982cf4SFabien Sanglard has_aspect_ratio_constraint;
604*3f982cf4SFabien Sanglard has_constraint_and_dimensions.dimensions =
605*3f982cf4SFabien Sanglard absl::optional<Dimensions>(kValidDimensions);
606*3f982cf4SFabien Sanglard
607*3f982cf4SFabien Sanglard DisplayDescription has_constraint_and_ratio = has_aspect_ratio_constraint;
608*3f982cf4SFabien Sanglard has_constraint_and_ratio.aspect_ratio = AspectRatio{4, 3};
609*3f982cf4SFabien Sanglard
610*3f982cf4SFabien Sanglard EXPECT_FALSE(kInvalidEmptyDescription.IsValid());
611*3f982cf4SFabien Sanglard EXPECT_TRUE(has_valid_dimensions.IsValid());
612*3f982cf4SFabien Sanglard EXPECT_FALSE(has_invalid_dimensions.IsValid());
613*3f982cf4SFabien Sanglard EXPECT_TRUE(has_aspect_ratio.IsValid());
614*3f982cf4SFabien Sanglard EXPECT_FALSE(has_invalid_aspect_ratio.IsValid());
615*3f982cf4SFabien Sanglard EXPECT_FALSE(has_aspect_ratio_constraint.IsValid());
616*3f982cf4SFabien Sanglard EXPECT_TRUE(has_constraint_and_dimensions.IsValid());
617*3f982cf4SFabien Sanglard }
618*3f982cf4SFabien Sanglard
619*3f982cf4SFabien Sanglard // Instead of being tested here, Answer's IsValid is checked in all other
620*3f982cf4SFabien Sanglard // relevant tests.
621*3f982cf4SFabien Sanglard
622*3f982cf4SFabien Sanglard } // namespace cast
623*3f982cf4SFabien Sanglard } // namespace openscreen
624