diff options
Diffstat (limited to 'cast/streaming/offer_messages_unittest.cc')
-rw-r--r-- | cast/streaming/offer_messages_unittest.cc | 191 |
1 files changed, 154 insertions, 37 deletions
diff --git a/cast/streaming/offer_messages_unittest.cc b/cast/streaming/offer_messages_unittest.cc index a2117f67..62685e4d 100644 --- a/cast/streaming/offer_messages_unittest.cc +++ b/cast/streaming/offer_messages_unittest.cc @@ -21,7 +21,6 @@ namespace { constexpr char kValidOffer[] = R"({ "castMode": "mirroring", - "receiverGetStatus": true, "supportedStreams": [ { "index": 0, @@ -82,6 +81,22 @@ constexpr char kValidOffer[] = R"({ "channels": 2, "aesKey": "51027e4e2347cbcb49d57ef10177aebc", "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1" + }, + { + "index": 3, + "type": "video_source", + "codecName": "av1", + "rtpProfile": "cast", + "rtpPayloadType": 104, + "ssrc": 19088744, + "maxFrameRate": "30000/1001", + "targetDelay": 1000, + "timeBase": "1/90000", + "maxBitRate": 5000000, + "profile": "main", + "level": "5", + "aesKey": "bbf109bf84513b456b13a184453b66ce", + "aesIvMask": "edaf9e4536e2b66191f560d9c04b2a69" } ] })"; @@ -91,24 +106,26 @@ void ExpectFailureOnParse( absl::optional<Error::Code> expected = absl::nullopt) { ErrorOr<Json::Value> root = json::Parse(body); ASSERT_TRUE(root.is_value()) << root.error(); - ErrorOr<Offer> error_or_offer = Offer::Parse(std::move(root.value())); - EXPECT_TRUE(error_or_offer.is_error()); + + Offer offer; + Error error = Offer::TryParse(std::move(root.value()), &offer); + EXPECT_FALSE(error.ok()); if (expected) { - EXPECT_EQ(expected, error_or_offer.error().code()); + EXPECT_EQ(expected, error.code()); } } void ExpectEqualsValidOffer(const Offer& offer) { EXPECT_EQ(CastMode::kMirroring, offer.cast_mode); - EXPECT_EQ(true, offer.supports_wifi_status_reporting); // Verify list of video streams. - EXPECT_EQ(2u, offer.video_streams.size()); + EXPECT_EQ(3u, offer.video_streams.size()); const auto& video_streams = offer.video_streams; const bool flipped = video_streams[0].stream.index != 0; - const VideoStream& vs_one = flipped ? video_streams[1] : video_streams[0]; - const VideoStream& vs_two = flipped ? video_streams[0] : video_streams[1]; + const VideoStream& vs_one = flipped ? video_streams[2] : video_streams[0]; + const VideoStream& vs_two = video_streams[1]; + const VideoStream& vs_three = flipped ? video_streams[0] : video_streams[2]; EXPECT_EQ(0, vs_one.stream.index); EXPECT_EQ(1, vs_one.stream.channels); @@ -163,6 +180,27 @@ void ExpectEqualsValidOffer(const Offer& offer) { const auto& resolutions_two = vs_two.resolutions; EXPECT_EQ(0u, resolutions_two.size()); + EXPECT_EQ(3, vs_three.stream.index); + EXPECT_EQ(1, vs_three.stream.channels); + EXPECT_EQ(Stream::Type::kVideoSource, vs_three.stream.type); + EXPECT_EQ(VideoCodec::kAv1, vs_three.codec); + EXPECT_EQ(RtpPayloadType::kVideoAv1, vs_three.stream.rtp_payload_type); + EXPECT_EQ(19088744u, vs_three.stream.ssrc); + EXPECT_EQ((SimpleFraction{30000, 1001}), vs_three.max_frame_rate); + EXPECT_EQ(90000, vs_three.stream.rtp_timebase); + EXPECT_EQ(5000000, vs_three.max_bit_rate); + EXPECT_EQ("main", vs_three.profile); + EXPECT_EQ("5", vs_three.level); + EXPECT_THAT(vs_three.stream.aes_key, + ElementsAre(0xbb, 0xf1, 0x09, 0xbf, 0x84, 0x51, 0x3b, 0x45, 0x6b, + 0x13, 0xa1, 0x84, 0x45, 0x3b, 0x66, 0xce)); + EXPECT_THAT(vs_three.stream.aes_iv_mask, + ElementsAre(0xed, 0xaf, 0x9e, 0x45, 0x36, 0xe2, 0xb6, 0x61, 0x91, + 0xf5, 0x60, 0xd9, 0xc0, 0x4b, 0x2a, 0x69)); + + const auto& resolutions_three = vs_three.resolutions; + EXPECT_EQ(0u, resolutions_three.size()); + // Verify list of audio streams. EXPECT_EQ(1u, offer.audio_streams.size()); const AudioStream& as = offer.audio_streams[0]; @@ -202,7 +240,9 @@ TEST(OfferTest, CanParseValidButStreamlessOffer) { "supportedStreams": [] })"); ASSERT_TRUE(root.is_value()) << root.error(); - EXPECT_TRUE(Offer::Parse(std::move(root.value())).is_value()); + + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); } TEST(OfferTest, ErrorOnMissingAudioStreamMandatoryField) { @@ -251,7 +291,8 @@ TEST(OfferTest, CanParseValidButMinimalAudioOffer) { }] })"); ASSERT_TRUE(root.is_value()); - EXPECT_TRUE(Offer::Parse(std::move(root.value())).is_value()); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); } TEST(OfferTest, CanParseValidZeroBitRateAudioOffer) { @@ -272,8 +313,8 @@ TEST(OfferTest, CanParseValidZeroBitRateAudioOffer) { }] })"); ASSERT_TRUE(root.is_value()) << root.error(); - const auto offer = Offer::Parse(std::move(root.value())); - EXPECT_TRUE(offer.is_value()) << offer.error(); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); } TEST(OfferTest, ErrorOnInvalidRtpTimebase) { @@ -422,6 +463,80 @@ TEST(OfferTest, ErrorOnMissingVideoStreamMandatoryField) { })"); } +TEST(OfferTest, ValidatesCodecParameterFormat) { + ExpectFailureOnParse(R"({ + "castMode": "mirroring", + "supportedStreams": [{ + "index": 2, + "type": "audio_source", + "codecName": "aac", + "codecParameter": "vp08.123.332", + "rtpProfile": "cast", + "rtpPayloadType": 96, + "ssrc": 19088743, + "bitRate": 124000, + "timeBase": "1/10000000", + "channels": 2, + "aesKey": "51027e4e2347cbcb49d57ef10177aebc", + "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1" + }] + })"); + + ExpectFailureOnParse(R"({ + "castMode": "mirroring", + "supportedStreams": [{ + "index": 2, + "type": "video_source", + "codecName": "vp8", + "codecParameter": "vp09.11.23", + "rtpProfile": "cast", + "rtpPayloadType": 100, + "ssrc": 19088743, + "timeBase": "1/48000", + "resolutions": [], + "maxBitRate": 10000, + "aesKey": "51027e4e2347cbcb49d57ef10177aebc" + }] + })"); + + const ErrorOr<Json::Value> audio_root = json::Parse(R"({ + "castMode": "mirroring", + "supportedStreams": [{ + "index": 2, + "type": "audio_source", + "codecName": "aac", + "codecParameter": "mp4a.12", + "rtpProfile": "cast", + "rtpPayloadType": 96, + "ssrc": 19088743, + "bitRate": 124000, + "timeBase": "1/10000000", + "channels": 2, + "aesKey": "51027e4e2347cbcb49d57ef10177aebc", + "aesIvMask": "7f12a19be62a36c04ae4116caaeff6d1" + }] + })"); + ASSERT_TRUE(audio_root.is_value()) << audio_root.error(); + + const ErrorOr<Json::Value> video_root = json::Parse(R"({ + "castMode": "mirroring", + "supportedStreams": [{ + "index": 2, + "type": "video_source", + "codecName": "vp9", + "codecParameter": "vp09.11.23", + "rtpProfile": "cast", + "rtpPayloadType": 100, + "ssrc": 19088743, + "timeBase": "1/48000", + "resolutions": [], + "maxBitRate": 10000, + "aesKey": "51027e4e2347cbcb49d57ef10177aebc" + }] + })"); + ASSERT_TRUE(video_root.is_value()) << video_root.error(); +} + TEST(OfferTest, CanParseValidButMinimalVideoOffer) { ErrorOr<Json::Value> root = json::Parse(R"({ "castMode": "mirroring", @@ -441,62 +556,64 @@ TEST(OfferTest, CanParseValidButMinimalVideoOffer) { })"); ASSERT_TRUE(root.is_value()); - EXPECT_TRUE(Offer::Parse(std::move(root.value())).is_value()); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); } TEST(OfferTest, CanParseValidOffer) { ErrorOr<Json::Value> root = json::Parse(kValidOffer); ASSERT_TRUE(root.is_value()); - ErrorOr<Offer> offer = Offer::Parse(std::move(root.value())); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); - ExpectEqualsValidOffer(offer.value()); + ExpectEqualsValidOffer(offer); } TEST(OfferTest, ParseAndToJsonResultsInSameOffer) { ErrorOr<Json::Value> root = json::Parse(kValidOffer); ASSERT_TRUE(root.is_value()); - ErrorOr<Offer> offer = Offer::Parse(std::move(root.value())); - - ExpectEqualsValidOffer(offer.value()); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); + ExpectEqualsValidOffer(offer); - auto eoj = offer.value().ToJson(); - EXPECT_TRUE(eoj.is_value()) << eoj.error(); - ErrorOr<Offer> reparsed_offer = Offer::Parse(std::move(eoj.value())); - ExpectEqualsValidOffer(reparsed_offer.value()); + Offer reparsed_offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &reparsed_offer).ok()); + ExpectEqualsValidOffer(reparsed_offer); } // We don't want to enforce that a given offer must have both audio and // video, so we don't assert on either. -TEST(OfferTest, ToJsonSucceedsWithMissingStreams) { +TEST(OfferTest, IsValidWithMissingStreams) { ErrorOr<Json::Value> root = json::Parse(kValidOffer); ASSERT_TRUE(root.is_value()); - ErrorOr<Offer> offer = Offer::Parse(std::move(root.value())); - ExpectEqualsValidOffer(offer.value()); - const Offer valid_offer = std::move(offer.value()); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); + ExpectEqualsValidOffer(offer); + const Offer valid_offer = std::move(offer); Offer missing_audio_streams = valid_offer; missing_audio_streams.audio_streams.clear(); - EXPECT_TRUE(missing_audio_streams.ToJson().is_value()); + EXPECT_TRUE(missing_audio_streams.IsValid()); Offer missing_video_streams = valid_offer; missing_video_streams.audio_streams.clear(); - EXPECT_TRUE(missing_video_streams.ToJson().is_value()); + EXPECT_TRUE(missing_video_streams.IsValid()); } -TEST(OfferTest, ToJsonFailsWithInvalidStreams) { +TEST(OfferTest, InvalidIfInvalidStreams) { ErrorOr<Json::Value> root = json::Parse(kValidOffer); ASSERT_TRUE(root.is_value()); - ErrorOr<Offer> offer = Offer::Parse(std::move(root.value())); - ExpectEqualsValidOffer(offer.value()); - const Offer valid_offer = std::move(offer.value()); + Offer offer; + EXPECT_TRUE(Offer::TryParse(std::move(root.value()), &offer).ok()); + ExpectEqualsValidOffer(offer); - Offer video_stream_invalid = valid_offer; - video_stream_invalid.video_streams[0].max_frame_rate.denominator = 0; - EXPECT_TRUE(video_stream_invalid.ToJson().is_error()); + Offer video_stream_invalid = offer; + video_stream_invalid.video_streams[0].max_frame_rate = SimpleFraction{1, 0}; + EXPECT_FALSE(video_stream_invalid.IsValid()); - Offer audio_stream_invalid = valid_offer; + Offer audio_stream_invalid = offer; video_stream_invalid.audio_streams[0].bit_rate = 0; - EXPECT_TRUE(video_stream_invalid.ToJson().is_error()); + EXPECT_FALSE(video_stream_invalid.IsValid()); } TEST(OfferTest, FailsIfUnencrypted) { |