diff --git a/pc/mediasession.cc b/pc/mediasession.cc index f53785df93..b20bf5fa86 100644 --- a/pc/mediasession.cc +++ b/pc/mediasession.cc @@ -2311,8 +2311,8 @@ const ContentInfo* GetFirstDataContent(const ContentInfos& contents) { return GetFirstMediaContent(contents, MEDIA_TYPE_DATA); } -static const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc, - MediaType media_type) { +const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc, + MediaType media_type) { if (sdesc == nullptr) { return nullptr; } @@ -2382,8 +2382,8 @@ ContentInfo* GetFirstDataContent(ContentInfos* contents) { return GetFirstMediaContent(contents, MEDIA_TYPE_DATA); } -static ContentInfo* GetFirstMediaContent(SessionDescription* sdesc, - MediaType media_type) { +ContentInfo* GetFirstMediaContent(SessionDescription* sdesc, + MediaType media_type) { if (sdesc == nullptr) { return nullptr; } diff --git a/pc/mediasession.h b/pc/mediasession.h index 7c531aaee6..02205c68af 100644 --- a/pc/mediasession.h +++ b/pc/mediasession.h @@ -287,6 +287,8 @@ const ContentInfo* GetFirstMediaContent(const ContentInfos& contents, const ContentInfo* GetFirstAudioContent(const ContentInfos& contents); const ContentInfo* GetFirstVideoContent(const ContentInfos& contents); const ContentInfo* GetFirstDataContent(const ContentInfos& contents); +const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc, + MediaType media_type); const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc); const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc); const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc); @@ -302,6 +304,8 @@ ContentInfo* GetFirstMediaContent(ContentInfos* contents, MediaType media_type); ContentInfo* GetFirstAudioContent(ContentInfos* contents); ContentInfo* GetFirstVideoContent(ContentInfos* contents); ContentInfo* GetFirstDataContent(ContentInfos* contents); +ContentInfo* GetFirstMediaContent(SessionDescription* sdesc, + MediaType media_type); ContentInfo* GetFirstAudioContent(SessionDescription* sdesc); ContentInfo* GetFirstVideoContent(SessionDescription* sdesc); ContentInfo* GetFirstDataContent(SessionDescription* sdesc); diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index fefa321b37..07e326d219 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -2190,9 +2190,6 @@ RTCError PeerConnection::UpdateTransceiversAndDataChannels( return transceiver_or_error.MoveError(); } auto transceiver = transceiver_or_error.MoveValue(); - if (source == cricket::CS_LOCAL && transceiver->stopped()) { - continue; - } RTCError error = UpdateTransceiverChannel(transceiver, new_content, bundle_group); if (!error.ok()) { diff --git a/pc/peerconnection_media_unittest.cc b/pc/peerconnection_media_unittest.cc index 79ffb8d935..40fc1ddad3 100644 --- a/pc/peerconnection_media_unittest.cc +++ b/pc/peerconnection_media_unittest.cc @@ -54,12 +54,14 @@ class PeerConnectionWrapperForMediaTest : public PeerConnectionWrapper { FakeMediaEngine* media_engine_; }; -class PeerConnectionMediaTest : public ::testing::Test { +class PeerConnectionMediaBaseTest : public ::testing::Test { protected: typedef std::unique_ptr WrapperPtr; - PeerConnectionMediaTest() - : vss_(new rtc::VirtualSocketServer()), main_(vss_.get()) { + explicit PeerConnectionMediaBaseTest(SdpSemantics sdp_semantics) + : vss_(new rtc::VirtualSocketServer()), + main_(vss_.get()), + sdp_semantics_(sdp_semantics) { #ifdef WEBRTC_ANDROID InitializeAndroidObjects(); #endif @@ -80,8 +82,11 @@ class PeerConnectionMediaTest : public ::testing::Test { auto fake_port_allocator = rtc::MakeUnique( rtc::Thread::Current(), nullptr); auto observer = rtc::MakeUnique(); - auto pc = pc_factory->CreatePeerConnection( - config, std::move(fake_port_allocator), nullptr, observer.get()); + auto modified_config = config; + modified_config.sdp_semantics = sdp_semantics_; + auto pc = pc_factory->CreatePeerConnection(modified_config, + std::move(fake_port_allocator), + nullptr, observer.get()); if (!pc) { return nullptr; } @@ -105,27 +110,44 @@ class PeerConnectionMediaTest : public ::testing::Test { return wrapper; } - const cricket::MediaContentDescription* GetMediaContent( - const SessionDescriptionInterface* sdesc, - const std::string& mid) { - const auto* content_desc = - sdesc->description()->GetContentDescriptionByName(mid); - return static_cast(content_desc); - } - RtpTransceiverDirection GetMediaContentDirection( const SessionDescriptionInterface* sdesc, - const std::string& mid) { - auto* media_content = GetMediaContent(sdesc, mid); - RTC_DCHECK(media_content); - return media_content->direction(); + cricket::MediaType media_type) { + auto* content = + cricket::GetFirstMediaContent(sdesc->description(), media_type); + RTC_DCHECK(content); + return content->media_description()->direction(); + } + + bool IsUnifiedPlan() const { + return sdp_semantics_ == SdpSemantics::kUnifiedPlan; } std::unique_ptr vss_; rtc::AutoSocketServerThread main_; + const SdpSemantics sdp_semantics_; }; -TEST_F(PeerConnectionMediaTest, +class PeerConnectionMediaTest + : public PeerConnectionMediaBaseTest, + public ::testing::WithParamInterface { + protected: + PeerConnectionMediaTest() : PeerConnectionMediaBaseTest(GetParam()) {} +}; + +class PeerConnectionMediaTestUnifiedPlan : public PeerConnectionMediaBaseTest { + protected: + PeerConnectionMediaTestUnifiedPlan() + : PeerConnectionMediaBaseTest(SdpSemantics::kUnifiedPlan) {} +}; + +class PeerConnectionMediaTestPlanB : public PeerConnectionMediaBaseTest { + protected: + PeerConnectionMediaTestPlanB() + : PeerConnectionMediaBaseTest(SdpSemantics::kPlanB) {} +}; + +TEST_P(PeerConnectionMediaTest, FailToSetRemoteDescriptionIfCreateMediaChannelFails) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnectionWithAudioVideo(); @@ -133,19 +155,19 @@ TEST_F(PeerConnectionMediaTest, std::string error; ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error)); - EXPECT_EQ("Failed to set remote offer sdp: Failed to create voice channel.", - error); + EXPECT_PRED_FORMAT2(AssertStartsWith, error, + "Failed to set remote offer sdp: Failed to create"); } -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, FailToSetLocalDescriptionIfCreateMediaChannelFails) { auto caller = CreatePeerConnectionWithAudioVideo(); caller->media_engine()->set_fail_create_channel(true); std::string error; ASSERT_FALSE(caller->SetLocalDescription(caller->CreateOffer(), &error)); - EXPECT_EQ("Failed to set local offer sdp: Failed to create voice channel.", - error); + EXPECT_PRED_FORMAT2(AssertStartsWith, error, + "Failed to set local offer sdp: Failed to create"); } std::vector GetIds( @@ -160,7 +182,7 @@ std::vector GetIds( // Test that exchanging an offer and answer with each side having an audio and // video stream creates the appropriate send/recv streams in the underlying // media engine on both sides. -TEST_F(PeerConnectionMediaTest, AudioVideoOfferAnswerCreateSendRecvStreams) { +TEST_P(PeerConnectionMediaTest, AudioVideoOfferAnswerCreateSendRecvStreams) { const std::string kCallerAudioId = "caller_a"; const std::string kCallerVideoId = "caller_v"; const std::string kCalleeAudioId = "callee_a"; @@ -203,91 +225,148 @@ TEST_F(PeerConnectionMediaTest, AudioVideoOfferAnswerCreateSendRecvStreams) { ElementsAre(kCalleeVideoId)); } +// Test that stopping the caller transceivers causes the media channels on the +// callee to be destroyed after calling SetRemoteDescription on the generated +// offer. +// See next test for equivalent behavior with Plan B semantics. +TEST_F(PeerConnectionMediaTestUnifiedPlan, + StoppedRemoteTransceiversRemovesMediaChannels) { + auto caller = CreatePeerConnectionWithAudioVideo(); + auto callee = CreatePeerConnection(); + + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); + + // Stop both audio and video transceivers on the caller. + auto transceivers = caller->pc()->GetTransceivers(); + ASSERT_EQ(2u, transceivers.size()); + transceivers[0]->Stop(); + transceivers[1]->Stop(); + + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); + + ASSERT_FALSE(callee->media_engine()->GetVoiceChannel(0)); + ASSERT_FALSE(callee->media_engine()->GetVideoChannel(0)); +} + // Test that removing streams from a subsequent offer causes the receive streams // on the callee to be removed. -TEST_F(PeerConnectionMediaTest, EmptyRemoteOfferRemovesRecvStreams) { +// See previous test for equivalent behavior with Unified Plan semantics. +TEST_F(PeerConnectionMediaTestPlanB, EmptyRemoteOfferRemovesRecvStreams) { auto caller = CreatePeerConnection(); auto caller_audio_track = caller->AddAudioTrack("a"); auto caller_video_track = caller->AddVideoTrack("v"); auto callee = CreatePeerConnectionWithAudioVideo(); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); // Remove both tracks from caller. caller->pc()->RemoveTrack(caller_audio_track); caller->pc()->RemoveTrack(caller_video_track); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); auto callee_voice = callee->media_engine()->GetVoiceChannel(0); + auto callee_video = callee->media_engine()->GetVideoChannel(0); EXPECT_EQ(1u, callee_voice->send_streams().size()); EXPECT_EQ(0u, callee_voice->recv_streams().size()); - - auto callee_video = callee->media_engine()->GetVideoChannel(0); EXPECT_EQ(1u, callee_video->send_streams().size()); EXPECT_EQ(0u, callee_video->recv_streams().size()); } +// Test that stopping the callee transceivers causes the media channels to be +// destroyed on the callee after calling SetLocalDescription on the local +// answer. +// See next test for equivalent behavior with Plan B semantics. +TEST_F(PeerConnectionMediaTestUnifiedPlan, + StoppedLocalTransceiversRemovesMediaChannels) { + auto caller = CreatePeerConnectionWithAudioVideo(); + auto callee = CreatePeerConnectionWithAudioVideo(); + + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); + + // Stop both audio and video transceivers on the callee. + auto transceivers = callee->pc()->GetTransceivers(); + ASSERT_EQ(2u, transceivers.size()); + transceivers[0]->Stop(); + transceivers[1]->Stop(); + + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); + + EXPECT_FALSE(callee->media_engine()->GetVoiceChannel(0)); + EXPECT_FALSE(callee->media_engine()->GetVideoChannel(0)); +} + // Test that removing streams from a subsequent answer causes the send streams // on the callee to be removed when applied locally. -TEST_F(PeerConnectionMediaTest, EmptyLocalAnswerRemovesSendStreams) { +// See previous test for equivalent behavior with Unified Plan semantics. +TEST_F(PeerConnectionMediaTestPlanB, EmptyLocalAnswerRemovesSendStreams) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnection(); auto callee_audio_track = callee->AddAudioTrack("a"); auto callee_video_track = callee->AddVideoTrack("v"); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); // Remove both tracks from callee. callee->pc()->RemoveTrack(callee_audio_track); callee->pc()->RemoveTrack(callee_video_track); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); auto callee_voice = callee->media_engine()->GetVoiceChannel(0); + auto callee_video = callee->media_engine()->GetVideoChannel(0); EXPECT_EQ(0u, callee_voice->send_streams().size()); EXPECT_EQ(1u, callee_voice->recv_streams().size()); - - auto callee_video = callee->media_engine()->GetVideoChannel(0); EXPECT_EQ(0u, callee_video->send_streams().size()); EXPECT_EQ(1u, callee_video->recv_streams().size()); } // Test that a new stream in a subsequent offer causes a new receive stream to // be created on the callee. -TEST_F(PeerConnectionMediaTest, NewStreamInRemoteOfferAddsRecvStreams) { +TEST_P(PeerConnectionMediaTest, NewStreamInRemoteOfferAddsRecvStreams) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnection(); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); // Add second set of tracks to the caller. caller->AddAudioTrack("a2"); caller->AddVideoTrack("v2"); - ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal())); - ASSERT_TRUE( - caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal())); + ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get())); - auto callee_voice = callee->media_engine()->GetVoiceChannel(0); - EXPECT_EQ(2u, callee_voice->recv_streams().size()); - auto callee_video = callee->media_engine()->GetVideoChannel(0); - EXPECT_EQ(2u, callee_video->recv_streams().size()); + auto a1 = callee->media_engine()->GetVoiceChannel(0); + auto a2 = callee->media_engine()->GetVoiceChannel(1); + auto v1 = callee->media_engine()->GetVideoChannel(0); + auto v2 = callee->media_engine()->GetVideoChannel(1); + if (IsUnifiedPlan()) { + ASSERT_TRUE(a1); + EXPECT_EQ(1u, a1->recv_streams().size()); + ASSERT_TRUE(a2); + EXPECT_EQ(1u, a2->recv_streams().size()); + ASSERT_TRUE(v1); + EXPECT_EQ(1u, v1->recv_streams().size()); + ASSERT_TRUE(v2); + EXPECT_EQ(1u, v2->recv_streams().size()); + } else { + ASSERT_TRUE(a1); + EXPECT_EQ(2u, a1->recv_streams().size()); + ASSERT_FALSE(a2); + ASSERT_TRUE(v1); + EXPECT_EQ(2u, v1->recv_streams().size()); + ASSERT_FALSE(v2); + } } // Test that a new stream in a subsequent answer causes a new send stream to be // created on the callee when added locally. -TEST_F(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) { +TEST_P(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } + auto caller = CreatePeerConnection(); auto callee = CreatePeerConnectionWithAudioVideo(); @@ -319,7 +398,7 @@ TEST_F(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) { // A PeerConnection with no local streams and no explicit answer constraints // should not reject any offered media sections. -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, CreateAnswerWithNoStreamsAndDefaultOptionsDoesNotReject) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnection(); @@ -338,14 +417,17 @@ TEST_F(PeerConnectionMediaTest, } class PeerConnectionMediaOfferDirectionTest - : public PeerConnectionMediaTest, + : public PeerConnectionMediaBaseTest, public ::testing::WithParamInterface< - std::tuple> { + std::tuple>> { protected: - PeerConnectionMediaOfferDirectionTest() { - send_media_ = std::get<0>(GetParam()); - offer_to_receive_ = std::get<1>(GetParam()); - expected_direction_ = std::get<2>(GetParam()); + PeerConnectionMediaOfferDirectionTest() + : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) { + auto param = std::get<1>(GetParam()); + send_media_ = std::get<0>(param); + offer_to_receive_ = std::get<1>(param); + expected_direction_ = std::get<2>(param); } bool send_media_; @@ -356,6 +438,11 @@ class PeerConnectionMediaOfferDirectionTest // Tests that the correct direction is set on the media description according // to the presence of a local media track and the offer_to_receive setting. TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } auto caller = CreatePeerConnection(); if (send_media_) { caller->AddAudioTrack("a"); @@ -365,11 +452,12 @@ TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) { options.offer_to_receive_audio = offer_to_receive_; auto offer = caller->CreateOffer(options); - auto* media_content = GetMediaContent(offer.get(), cricket::CN_AUDIO); + auto* content = cricket::GetFirstMediaContent(offer->description(), + cricket::MEDIA_TYPE_AUDIO); if (expected_direction_ == RtpTransceiverDirection::kInactive) { - EXPECT_FALSE(media_content); + EXPECT_FALSE(content); } else { - EXPECT_EQ(expected_direction_, media_content->direction()); + EXPECT_EQ(expected_direction_, content->media_description()->direction()); } } @@ -378,22 +466,25 @@ TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) { INSTANTIATE_TEST_CASE_P( PeerConnectionMediaTest, PeerConnectionMediaOfferDirectionTest, - Values(std::make_tuple(false, -1, RtpTransceiverDirection::kInactive), - std::make_tuple(false, 0, RtpTransceiverDirection::kInactive), - std::make_tuple(false, 1, RtpTransceiverDirection::kRecvOnly), - std::make_tuple(true, -1, RtpTransceiverDirection::kSendRecv), - std::make_tuple(true, 0, RtpTransceiverDirection::kSendOnly), - std::make_tuple(true, 1, RtpTransceiverDirection::kSendRecv))); + Combine( + Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan), + Values(std::make_tuple(false, -1, RtpTransceiverDirection::kInactive), + std::make_tuple(false, 0, RtpTransceiverDirection::kInactive), + std::make_tuple(false, 1, RtpTransceiverDirection::kRecvOnly), + std::make_tuple(true, -1, RtpTransceiverDirection::kSendRecv), + std::make_tuple(true, 0, RtpTransceiverDirection::kSendOnly), + std::make_tuple(true, 1, RtpTransceiverDirection::kSendRecv)))); class PeerConnectionMediaAnswerDirectionTest - : public PeerConnectionMediaTest, + : public PeerConnectionMediaBaseTest, public ::testing::WithParamInterface< - std::tuple> { + std::tuple> { protected: - PeerConnectionMediaAnswerDirectionTest() { - offer_direction_ = std::get<0>(GetParam()); - send_media_ = std::get<1>(GetParam()); - offer_to_receive_ = std::get<2>(GetParam()); + PeerConnectionMediaAnswerDirectionTest() + : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) { + offer_direction_ = std::get<1>(GetParam()); + send_media_ = std::get<2>(GetParam()); + offer_to_receive_ = std::get<3>(GetParam()); } RtpTransceiverDirection offer_direction_; @@ -405,6 +496,11 @@ class PeerConnectionMediaAnswerDirectionTest // in the offer, the presence of a local media track on the receive side and the // offer_to_receive setting. TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } auto caller = CreatePeerConnection(); caller->AddAudioTrack("a"); @@ -441,13 +537,18 @@ TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) { auto expected_direction = RtpTransceiverDirectionFromSendRecv(negotiate_send, negotiate_recv); EXPECT_EQ(expected_direction, - GetMediaContentDirection(answer.get(), cricket::CN_AUDIO)); + GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO)); } // Tests that the media section is rejected if and only if the callee has no // local media track and has set offer_to_receive to 0, no matter which // direction the caller indicated in the offer. TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } auto caller = CreatePeerConnection(); caller->AddAudioTrack("a"); @@ -476,14 +577,22 @@ TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) { INSTANTIATE_TEST_CASE_P(PeerConnectionMediaTest, PeerConnectionMediaAnswerDirectionTest, - Combine(Values(RtpTransceiverDirection::kInactive, + Combine(Values(SdpSemantics::kPlanB, + SdpSemantics::kUnifiedPlan), + Values(RtpTransceiverDirection::kInactive, RtpTransceiverDirection::kSendOnly, RtpTransceiverDirection::kRecvOnly, RtpTransceiverDirection::kSendRecv), Bool(), Values(-1, 0, 1))); -TEST_F(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) { +TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } + auto caller = CreatePeerConnection(); caller->AddVideoTrack("v"); @@ -493,12 +602,18 @@ TEST_F(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) { auto offer = caller->CreateOffer(options); EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, - GetMediaContentDirection(offer.get(), cricket::CN_AUDIO)); + GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_AUDIO)); EXPECT_EQ(RtpTransceiverDirection::kSendOnly, - GetMediaContentDirection(offer.get(), cricket::CN_VIDEO)); + GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_VIDEO)); } -TEST_F(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) { +TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } + auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnection(); callee->AddVideoTrack("v"); @@ -511,9 +626,9 @@ TEST_F(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) { auto answer = callee->CreateAnswer(options); EXPECT_EQ(RtpTransceiverDirection::kRecvOnly, - GetMediaContentDirection(answer.get(), cricket::CN_AUDIO)); + GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO)); EXPECT_EQ(RtpTransceiverDirection::kSendOnly, - GetMediaContentDirection(answer.get(), cricket::CN_VIDEO)); + GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_VIDEO)); } void AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine* media_engine) { @@ -536,7 +651,7 @@ bool HasAnyComfortNoiseCodecs(const cricket::SessionDescription* desc) { return false; } -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, CreateOfferWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) { auto caller = CreatePeerConnectionWithAudioVideo(); AddComfortNoiseCodecsToSend(caller->media_engine()); @@ -548,7 +663,7 @@ TEST_F(PeerConnectionMediaTest, EXPECT_FALSE(HasAnyComfortNoiseCodecs(offer->description())); } -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, CreateAnswerWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) { auto caller = CreatePeerConnectionWithAudioVideo(); AddComfortNoiseCodecsToSend(caller->media_engine()); @@ -568,15 +683,18 @@ TEST_F(PeerConnectionMediaTest, // sections as per RFC 3264. class PeerConnectionMediaInvalidMediaTest - : public PeerConnectionMediaTest, - public ::testing::WithParamInterface< + : public PeerConnectionMediaBaseTest, + public ::testing::WithParamInterface, - std::string>> { + std::string>>> { protected: - PeerConnectionMediaInvalidMediaTest() { - mutator_ = std::get<1>(GetParam()); - expected_error_ = std::get<2>(GetParam()); + PeerConnectionMediaInvalidMediaTest() + : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) { + auto param = std::get<1>(GetParam()); + mutator_ = std::get<1>(param); + expected_error_ = std::get<2>(param); } std::function mutator_; @@ -630,9 +748,10 @@ void ReverseMediaContent(cricket::SessionDescription* desc) { } void ChangeMediaTypeAudioToVideo(cricket::SessionDescription* desc) { - desc->RemoveContentByName(cricket::CN_AUDIO); - auto* video_content = desc->GetContentByName(cricket::CN_VIDEO); - desc->AddContent(cricket::CN_AUDIO, video_content->type, + std::string audio_mid = cricket::GetFirstAudioContent(desc)->name; + desc->RemoveContentByName(audio_mid); + auto* video_content = cricket::GetFirstVideoContent(desc); + desc->AddContent(audio_mid, video_content->type, video_content->media_description()->Copy()); } @@ -643,20 +762,30 @@ constexpr char kMLinesOutOfOrder[] = INSTANTIATE_TEST_CASE_P( PeerConnectionMediaTest, PeerConnectionMediaInvalidMediaTest, - Values( - std::make_tuple("remove video", RemoveVideoContent, kMLinesOutOfOrder), - std::make_tuple("rename video", RenameVideoContent, kMLinesOutOfOrder), - std::make_tuple("reverse media sections", - ReverseMediaContent, - kMLinesOutOfOrder), - std::make_tuple("change audio type to video type", - ChangeMediaTypeAudioToVideo, - kMLinesOutOfOrder))); + Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan), + Values(std::make_tuple("remove video", + RemoveVideoContent, + kMLinesOutOfOrder), + std::make_tuple("rename video", + RenameVideoContent, + kMLinesOutOfOrder), + std::make_tuple("reverse media sections", + ReverseMediaContent, + kMLinesOutOfOrder), + std::make_tuple("change audio type to video type", + ChangeMediaTypeAudioToVideo, + kMLinesOutOfOrder)))); // Test that the correct media engine send/recv streams are created when doing // a series of offer/answers where audio/video are both sent, then audio is // rejected, then both audio/video sent again. -TEST_F(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) { +TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } + RTCOfferAnswerOptions options_reject_video; options_reject_video.offer_to_receive_audio = RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; @@ -714,7 +843,13 @@ TEST_F(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) { // Test that the correct media engine send/recv streams are created when doing // a series of offer/answers where audio/video are both sent, then video is // rejected, then both audio/video sent again. -TEST_F(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) { +TEST_P(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) { + // TODO(bugs.webrtc.org/8765): Enable this test under Unified Plan once + // offer_to_receive_audio is implemented. + if (IsUnifiedPlan()) { + return; + } + // Disable the bundling here. If the media is bundled on audio // transport, then we can't reject the audio because switching the bundled // transport is not currently supported. @@ -778,7 +913,7 @@ TEST_F(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) { // Tests that if the underlying video encoder fails to be initialized (signaled // by failing to set send codecs), the PeerConnection signals the error to the // client. -TEST_F(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) { +TEST_P(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnectionWithAudioVideo(); @@ -800,7 +935,7 @@ TEST_F(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) { // Tests that if the underlying video encoder fails once then subsequent // attempts at setting the local/remote description will also fail, even if // SetSendCodecs no longer fails. -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, FailToApplyDescriptionIfVideoEncoderHasEverFailed) { auto caller = CreatePeerConnectionWithAudioVideo(); auto callee = CreatePeerConnectionWithAudioVideo(); @@ -820,10 +955,11 @@ TEST_F(PeerConnectionMediaTest, } void RenameContent(cricket::SessionDescription* desc, - const std::string& old_name, + cricket::MediaType media_type, const std::string& new_name) { - auto* content = desc->GetContentByName(old_name); + auto* content = cricket::GetFirstMediaContent(desc, media_type); RTC_DCHECK(content); + std::string old_name = content->name; content->name = new_name; auto* transport = desc->GetTransportInfoByName(old_name); RTC_DCHECK(transport); @@ -831,7 +967,7 @@ void RenameContent(cricket::SessionDescription* desc, } // Tests that an answer responds with the same MIDs as the offer. -TEST_F(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) { +TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) { const std::string kAudioMid = "not default1"; const std::string kVideoMid = "not default2"; @@ -839,8 +975,8 @@ TEST_F(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) { auto callee = CreatePeerConnectionWithAudioVideo(); auto offer = caller->CreateOffer(); - RenameContent(offer->description(), cricket::CN_AUDIO, kAudioMid); - RenameContent(offer->description(), cricket::CN_VIDEO, kVideoMid); + RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid); + RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid); ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer))); auto answer = callee->CreateAnswer(); @@ -852,7 +988,7 @@ TEST_F(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) { // Test that if the callee creates a re-offer, the MIDs are the same as the // original offer. -TEST_F(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) { +TEST_P(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) { const std::string kAudioMid = "not default1"; const std::string kVideoMid = "not default2"; @@ -860,8 +996,8 @@ TEST_F(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) { auto callee = CreatePeerConnectionWithAudioVideo(); auto offer = caller->CreateOffer(); - RenameContent(offer->description(), cricket::CN_AUDIO, kAudioMid); - RenameContent(offer->description(), cricket::CN_VIDEO, kVideoMid); + RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid); + RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid); ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer))); ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer())); @@ -872,7 +1008,7 @@ TEST_F(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) { cricket::GetFirstVideoContent(reoffer->description())->name); } -TEST_F(PeerConnectionMediaTest, +TEST_P(PeerConnectionMediaTest, CombinedAudioVideoBweConfigPropagatedToMediaEngine) { RTCConfiguration config; config.combined_audio_video_bwe.emplace(true); @@ -887,4 +1023,9 @@ TEST_F(PeerConnectionMediaTest, audio_options.combined_audio_video_bwe); } +INSTANTIATE_TEST_CASE_P(PeerConnectionMediaTest, + PeerConnectionMediaTest, + Values(SdpSemantics::kPlanB, + SdpSemantics::kUnifiedPlan)); + } // namespace webrtc diff --git a/pc/peerconnection_signaling_unittest.cc b/pc/peerconnection_signaling_unittest.cc index 282ce1ce53..cd26f8ba51 100644 --- a/pc/peerconnection_signaling_unittest.cc +++ b/pc/peerconnection_signaling_unittest.cc @@ -209,19 +209,6 @@ class PeerConnectionSignalingStateTest } }; -::testing::AssertionResult AssertStartsWith(const char* str_expr, - const char* prefix_expr, - const std::string& str, - const std::string& prefix) { - if (rtc::starts_with(str.c_str(), prefix.c_str())) { - return ::testing::AssertionSuccess(); - } else { - return ::testing::AssertionFailure() - << str_expr << "\nwhich is\n\"" << str << "\"\ndoes not start with\n" - << prefix_expr << "\nwhich is\n\"" << prefix << "\""; - } -} - TEST_P(PeerConnectionSignalingStateTest, CreateOffer) { auto wrapper = CreatePeerConnectionInState(GetParam()); if (wrapper->signaling_state() != SignalingState::kClosed) { diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index c665e03914..10c73887bf 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -832,6 +832,7 @@ rtc_source_set("rtc_base_tests_utils") { "fakesslidentity.h", "firewallsocketserver.cc", "firewallsocketserver.h", + "gunit.cc", "gunit.h", "httpbase.cc", "httpbase.h", diff --git a/rtc_base/gunit.cc b/rtc_base/gunit.cc new file mode 100644 index 0000000000..c4631cdcdc --- /dev/null +++ b/rtc_base/gunit.cc @@ -0,0 +1,28 @@ +/* + * Copyright 2018 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "rtc_base/gunit.h" + +#include + +#include "rtc_base/stringutils.h" + +::testing::AssertionResult AssertStartsWith(const char* str_expr, + const char* prefix_expr, + const std::string& str, + const std::string& prefix) { + if (rtc::starts_with(str.c_str(), prefix.c_str())) { + return ::testing::AssertionSuccess(); + } else { + return ::testing::AssertionFailure() + << str_expr << "\nwhich is\n\"" << str << "\"\ndoes not start with\n" + << prefix_expr << "\nwhich is\n\"" << prefix << "\""; + } +} diff --git a/rtc_base/gunit.h b/rtc_base/gunit.h index 9ee3c72ad5..ee62d35dcc 100644 --- a/rtc_base/gunit.h +++ b/rtc_base/gunit.h @@ -157,4 +157,10 @@ } else \ GTEST_CONCAT_TOKEN_(gunit_label_, __LINE__) : ASSERT_EQ(v1, v2) +// Usage: EXPECT_PRED_FORMAT2(AssertStartsWith, str, "prefix"); +testing::AssertionResult AssertStartsWith(const char* str_expr, + const char* prefix_expr, + const std::string& str, + const std::string& prefix); + #endif // RTC_BASE_GUNIT_H_