Chromium Code Reviews| Index: webrtc/pc/mediasession_unittest.cc |
| diff --git a/webrtc/pc/mediasession_unittest.cc b/webrtc/pc/mediasession_unittest.cc |
| index b1c4044b707699f88125ec2696534e597b952c9a..684e2a70194d4fc147a9d11bbc3aa355b9dde5ae 100644 |
| --- a/webrtc/pc/mediasession_unittest.cc |
| +++ b/webrtc/pc/mediasession_unittest.cc |
| @@ -39,6 +39,7 @@ typedef std::vector<cricket::Candidate> Candidates; |
| using cricket::MediaContentDescription; |
| using cricket::MediaSessionDescriptionFactory; |
| +using cricket::MediaContentDirection; |
| using cricket::MediaSessionOptions; |
| using cricket::MediaType; |
| using cricket::SessionDescription; |
| @@ -93,6 +94,11 @@ static const AudioCodec kAudioCodecsAnswer[] = { |
| AudioCodec(0, "PCMU", 8000, 64000, 1), |
| }; |
| +static const AudioCodec kAudioCodecsAnswer2[] = { |
| + AudioCodec(0, "PCMU", 8000, 64000, 1), |
| + AudioCodec(127, "iLBC", 8000, 13300, 1), |
| +}; |
| + |
| static const VideoCodec kVideoCodecs1[] = { |
| VideoCodec(96, "H264-SVC", 320, 200, 30), |
| VideoCodec(97, "H264", 320, 200, 30)}; |
| @@ -2450,3 +2456,243 @@ INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest, |
| INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest, |
| MediaProtocolTest, |
| ::testing::ValuesIn(kMediaProtocolsDtls)); |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecsOld) { |
| + TransportDescriptionFactory tdf; |
| + MediaSessionDescriptionFactory sf(&tdf); |
| + const std::vector<AudioCodec> codecs = MAKE_VECTOR(kAudioCodecs1); |
| + sf.set_audio_codecs(codecs); |
| + |
| + EXPECT_TRUE(sf.audio_codecs() == codecs); |
| + EXPECT_TRUE(sf.audio_send_codecs() == codecs); |
| + EXPECT_TRUE(sf.audio_recv_codecs() == codecs); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) { |
| + TransportDescriptionFactory tdf; |
| + MediaSessionDescriptionFactory sf(&tdf); |
| + std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
| + std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
| + |
| + // The merged list of codecs should contain any send codecs that are also |
| + // nominally in the recieve codecs list. Payload types should be picked from |
| + // the send codecs and a number-of-channels of 0 and 1 should be equivalent |
| + // (set to 1). This equals what happens when the send codecs are used in an |
| + // offer and the receive codecs are used in the following answer. |
| + const std::vector<AudioCodec> sendrecv_codecs = |
| + MAKE_VECTOR(kAudioCodecsAnswer); |
| + const std::vector<AudioCodec> no_codecs; |
| + |
| + RTC_CHECK_EQ(send_codecs[1].name, "iLBC") |
| + << "Please don't change shared test data!"; |
| + RTC_CHECK_EQ(recv_codecs[2].name, "iLBC") |
| + << "Please don't change shared test data!"; |
| + // Alter iLBC send codec to have zero channels, to test that that is handled |
| + // properly. |
| + send_codecs[1].channels = 0; |
| + |
| + // Alther iLBC receive codec to be lowercase, to test that case conversions |
| + // are handled properly. |
| + recv_codecs[2].name = "ilbc"; |
| + |
| + // Test proper merge |
| + sf.set_audio_codecs(send_codecs, recv_codecs); |
| + EXPECT_TRUE(sf.audio_send_codecs() == send_codecs); |
| + EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs); |
| + EXPECT_TRUE(sf.audio_codecs() == sendrecv_codecs); |
| + |
| + // Test empty send codecs list |
| + sf.set_audio_codecs(no_codecs, recv_codecs); |
| + EXPECT_TRUE(sf.audio_send_codecs() == no_codecs); |
| + EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs); |
| + EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
| + |
| + // Test empty recv codecs list |
| + sf.set_audio_codecs(send_codecs, no_codecs); |
| + EXPECT_TRUE(sf.audio_send_codecs() == send_codecs); |
| + EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs); |
| + EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
| + |
| + // Test all empty codec lists |
| + sf.set_audio_codecs(no_codecs, no_codecs); |
| + EXPECT_TRUE(sf.audio_send_codecs() == no_codecs); |
| + EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs); |
| + EXPECT_TRUE(sf.audio_codecs() == no_codecs); |
| +} |
| + |
| +namespace { |
| +void TestAudioCodecsOffer(MediaContentDirection direction) { |
| + TransportDescriptionFactory tdf; |
| + MediaSessionDescriptionFactory sf(&tdf); |
| + const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
| + const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
| + const std::vector<AudioCodec> sendrecv_codecs = |
| + MAKE_VECTOR(kAudioCodecsAnswer); |
| + sf.set_audio_codecs(send_codecs, recv_codecs); |
| + |
| + // Don't add a legacy stream whenever we've not provided a stream ourselves. |
| + sf.set_add_legacy_streams(false); |
| + MediaSessionOptions opts; |
| + opts.recv_audio = (direction == cricket::MD_RECVONLY || |
| + direction == cricket::MD_SENDRECV); |
| + opts.recv_video = false; |
| + if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV) |
| + opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
| + |
| + std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL)); |
| + ASSERT_TRUE(offer.get() != NULL); |
| + const ContentInfo* ac = offer->GetContentByName("audio"); |
| + |
| + // If the factory didn't add any audio content to the offer, we cannot check |
| + // that the codecs put in are right. This happens when we neither want to send |
| + // nor receive audio. The checks are still in place if at some point we'd |
| + // instead create an inactive stream. |
| + if (ac) { |
| + AudioContentDescription* acd = |
| + static_cast<AudioContentDescription*>(ac->description); |
| + // sendrecv and inactive should both present lists as if the channel was to |
| + // be used for sending and receiving. Inactive essentially means it might |
| + // eventually be used anything, but we don't know more at this moment. |
| + if (acd->direction() == cricket::MD_SENDONLY) { |
| + EXPECT_TRUE(acd->codecs() == send_codecs); |
| + } else if (acd->direction() == cricket::MD_RECVONLY) { |
| + EXPECT_TRUE(acd->codecs() == recv_codecs); |
| + } else { |
| + EXPECT_TRUE(acd->codecs() == sendrecv_codecs); |
| + } |
| + } |
| +} |
| + |
| +void TestAudioCodecsAnswer(MediaContentDirection offer_direction, |
| + MediaContentDirection answer_direction) { |
| + TransportDescriptionFactory offer_tdf; |
| + TransportDescriptionFactory answer_tdf; |
| + MediaSessionDescriptionFactory offer_factory(&offer_tdf); |
| + MediaSessionDescriptionFactory answer_factory(&answer_tdf); |
| + const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1); |
| + const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2); |
| + const std::vector<AudioCodec> answerer_sendrecv_codecs = |
| + MAKE_VECTOR(kAudioCodecsAnswer); |
| + const std::vector<AudioCodec> offerer_sendrecv_codecs = |
| + MAKE_VECTOR(kAudioCodecsAnswer2); |
| + // Send and receive are from the perspective of the answerer (since we're |
| + // testing the answer generation). |
| + offer_factory.set_audio_codecs(recv_codecs, send_codecs); |
| + answer_factory.set_audio_codecs(send_codecs, recv_codecs); |
| + |
| + // Don't add a legacy stream whenever we've not provided a stream ourselves. |
| + offer_factory.set_add_legacy_streams(false); |
| + answer_factory.set_add_legacy_streams(false); |
| + MediaSessionOptions offer_opts; |
| + offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY || |
| + offer_direction == cricket::MD_SENDRECV); |
| + offer_opts.recv_video = false; |
| + if (offer_direction == cricket::MD_SENDONLY || |
| + offer_direction == cricket::MD_SENDRECV) { |
| + offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
| + } |
| + |
| + std::unique_ptr<SessionDescription> offer( |
| + offer_factory.CreateOffer(offer_opts, NULL)); |
| + ASSERT_TRUE(offer.get() != NULL); |
| + |
| + MediaSessionOptions answer_opts; |
| + answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY || |
| + answer_direction == cricket::MD_SENDRECV); |
| + answer_opts.recv_video = false; |
| + if (answer_direction == cricket::MD_SENDONLY || |
| + answer_direction == cricket::MD_SENDRECV) { |
| + answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1); |
| + } |
| + std::unique_ptr<SessionDescription> answer( |
| + answer_factory.CreateAnswer(offer.get(), answer_opts, NULL)); |
| + const ContentInfo* ac = answer->GetContentByName("audio"); |
| + |
| + // If the factory didn't add any audio content to the answer, we cannot check |
| + // that the codecs put in are right. This happens when we neither want to send |
| + // nor receive audio. The checks are still in place if at some point we'd |
| + // instead create an inactive stream. |
| + if (ac) { |
| + const AudioContentDescription* acd = |
| + static_cast<const AudioContentDescription*>(ac->description); |
| + EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type()); |
| + |
| + // For offers with sendrecv or inactive, we should never reply with more |
| + // codecs than offered, with these codec sets. |
| + if (offer_direction == cricket::MD_SENDRECV || |
| + offer_direction == cricket::MD_INACTIVE) { |
| + EXPECT_TRUE(acd->codecs() == offerer_sendrecv_codecs) |
| + << "Offered: " << MediaContentDirectionToString(offer_direction) |
| + << ", answerer wants: " |
| + << MediaContentDirectionToString(answer_direction) |
| + << "; got: " << MediaContentDirectionToString(acd->direction()); |
| + } else { |
| + // Otherwise, the codecs in the answer should depend only on the direction |
| + // we picked in our answer. |
| + if (acd->direction() == cricket::MD_SENDONLY) { |
| + EXPECT_TRUE(acd->codecs() == send_codecs) |
| + << "Offered: " << MediaContentDirectionToString(offer_direction) |
| + << ", answerer wants: " |
| + << MediaContentDirectionToString(answer_direction) |
| + << "; got: " << MediaContentDirectionToString(acd->direction()); |
| + } else if (acd->direction() == cricket::MD_RECVONLY) { |
| + EXPECT_TRUE(acd->codecs() == recv_codecs) |
| + << "Offered: " << MediaContentDirectionToString(offer_direction) |
| + << ", answerer wants: " |
| + << MediaContentDirectionToString(answer_direction) |
| + << "; got: " << MediaContentDirectionToString(acd->direction()); |
| + } else { |
| + EXPECT_TRUE(acd->codecs() == answerer_sendrecv_codecs) |
| + << "Offered: " << MediaContentDirectionToString(offer_direction) |
| + << ", answerer wants: " |
| + << MediaContentDirectionToString(answer_direction) |
| + << "; got: " << MediaContentDirectionToString(acd->direction()); |
| + } |
| + } |
| + } |
| +} |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendOnlyCodecsOffer) { |
| + TestAudioCodecsOffer(cricket::MD_SENDONLY); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioRecvOnlyCodecsOffer) { |
| + TestAudioCodecsOffer(cricket::MD_RECVONLY); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendRecvCodecsOffer) { |
| + TestAudioCodecsOffer(cricket::MD_SENDRECV); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioInactiveCodecsOffer) { |
| + TestAudioCodecsOffer(cricket::MD_INACTIVE); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendOnlyCodecsAnswer) { |
|
ossu
2016/05/23 14:18:04
I grouped them by the expected resulting direction
|
| + TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY); |
| + TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_SENDRECV); |
| + TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_SENDONLY); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioRecvOnlyCodecsAnswer) { |
| + TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY); |
| + TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_SENDRECV); |
| + TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_RECVONLY); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioSendRecvCodecsAnswer) { |
| + TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV); |
| +} |
| + |
| +TEST_F(MediaSessionDescriptionFactoryTest, TestAudioInactiveCodecsAnswer) { |
| + TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE); |
| + TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_SENDONLY); |
| + TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_RECVONLY); |
| + TestAudioCodecsAnswer(cricket::MD_INACTIVE, cricket::MD_SENDRECV); |
| + TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_RECVONLY); |
| + TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_SENDONLY); |
| + TestAudioCodecsAnswer(cricket::MD_RECVONLY, cricket::MD_INACTIVE); |
| + TestAudioCodecsAnswer(cricket::MD_SENDONLY, cricket::MD_INACTIVE); |
| + TestAudioCodecsAnswer(cricket::MD_SENDRECV, cricket::MD_INACTIVE); |
| +} |