- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / session / media / mediasession_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2004 Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <string>
29 #include <vector>
30
31 #include "talk/base/gunit.h"
32 #include "talk/base/fakesslidentity.h"
33 #include "talk/base/messagedigest.h"
34 #include "talk/media/base/codec.h"
35 #include "talk/media/base/testutils.h"
36 #include "talk/p2p/base/constants.h"
37 #include "talk/p2p/base/transportdescription.h"
38 #include "talk/p2p/base/transportinfo.h"
39 #include "talk/session/media/mediasession.h"
40 #include "talk/session/media/srtpfilter.h"
41
42 #ifdef HAVE_SRTP
43 #define ASSERT_CRYPTO(cd, s, cs) \
44     ASSERT_FALSE(cd->crypto_required()); \
45     ASSERT_EQ(s, cd->cryptos().size()); \
46     ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
47 #else
48 #define ASSERT_CRYPTO(cd, s, cs) \
49   ASSERT_FALSE(cd->crypto_required()); \
50   ASSERT_EQ(0U, cd->cryptos().size());
51 #endif
52
53 typedef std::vector<cricket::Candidate> Candidates;
54
55 using cricket::MediaContentDescription;
56 using cricket::MediaSessionDescriptionFactory;
57 using cricket::MediaSessionOptions;
58 using cricket::MediaType;
59 using cricket::SessionDescription;
60 using cricket::SsrcGroup;
61 using cricket::StreamParams;
62 using cricket::StreamParamsVec;
63 using cricket::TransportDescription;
64 using cricket::TransportDescriptionFactory;
65 using cricket::TransportInfo;
66 using cricket::ContentInfo;
67 using cricket::CryptoParamsVec;
68 using cricket::AudioContentDescription;
69 using cricket::VideoContentDescription;
70 using cricket::DataContentDescription;
71 using cricket::GetFirstAudioContentDescription;
72 using cricket::GetFirstVideoContentDescription;
73 using cricket::GetFirstDataContentDescription;
74 using cricket::kAutoBandwidth;
75 using cricket::AudioCodec;
76 using cricket::VideoCodec;
77 using cricket::DataCodec;
78 using cricket::NS_JINGLE_RTP;
79 using cricket::MEDIA_TYPE_AUDIO;
80 using cricket::MEDIA_TYPE_VIDEO;
81 using cricket::MEDIA_TYPE_DATA;
82 using cricket::RtpHeaderExtension;
83 using cricket::SEC_DISABLED;
84 using cricket::SEC_ENABLED;
85 using cricket::SEC_REQUIRED;
86 using cricket::CS_AES_CM_128_HMAC_SHA1_32;
87 using cricket::CS_AES_CM_128_HMAC_SHA1_80;
88
89 static const AudioCodec kAudioCodecs1[] = {
90   AudioCodec(103, "ISAC",   16000, -1,    1, 6),
91   AudioCodec(102, "iLBC",   8000,  13300, 1, 5),
92   AudioCodec(0,   "PCMU",   8000,  64000, 1, 4),
93   AudioCodec(8,   "PCMA",   8000,  64000, 1, 3),
94   AudioCodec(117, "red",    8000,  0,     1, 2),
95   AudioCodec(107, "CN",     48000, 0,     1, 1)
96 };
97
98 static const AudioCodec kAudioCodecs2[] = {
99   AudioCodec(126, "speex",  16000, 22000, 1, 3),
100   AudioCodec(127, "iLBC",   8000,  13300, 1, 2),
101   AudioCodec(0,   "PCMU",   8000,  64000, 1, 1),
102 };
103
104 static const AudioCodec kAudioCodecsAnswer[] = {
105   AudioCodec(102, "iLBC",   8000,  13300, 1, 2),
106   AudioCodec(0,   "PCMU",   8000,  64000, 1, 1),
107 };
108
109 static const VideoCodec kVideoCodecs1[] = {
110   VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
111   VideoCodec(97, "H264", 320, 200, 30, 1)
112 };
113
114 static const VideoCodec kVideoCodecs2[] = {
115   VideoCodec(126, "H264", 320, 200, 30, 2),
116   VideoCodec(127, "H263", 320, 200, 30, 1)
117 };
118
119 static const VideoCodec kVideoCodecsAnswer[] = {
120   VideoCodec(97, "H264", 320, 200, 30, 2)
121 };
122
123 static const DataCodec kDataCodecs1[] = {
124   DataCodec(98, "binary-data", 2),
125   DataCodec(99, "utf8-text", 1)
126 };
127
128 static const DataCodec kDataCodecs2[] = {
129   DataCodec(126, "binary-data", 2),
130   DataCodec(127, "utf8-text", 1)
131 };
132
133 static const DataCodec kDataCodecsAnswer[] = {
134   DataCodec(98, "binary-data", 2),
135   DataCodec(99, "utf8-text", 1)
136 };
137
138 static const RtpHeaderExtension kAudioRtpExtension1[] = {
139   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
140   RtpHeaderExtension("http://google.com/testing/audio_something", 10),
141 };
142
143 static const RtpHeaderExtension kAudioRtpExtension2[] = {
144   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
145   RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
146 };
147
148 static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
149   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
150 };
151
152 static const RtpHeaderExtension kVideoRtpExtension1[] = {
153   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
154   RtpHeaderExtension("http://google.com/testing/video_something", 15),
155 };
156
157 static const RtpHeaderExtension kVideoRtpExtension2[] = {
158   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
159   RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
160 };
161
162 static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
163   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
164 };
165
166 static const uint32 kFec1Ssrc[] = {10, 11};
167 static const uint32 kFec2Ssrc[] = {20, 21};
168 static const uint32 kFec3Ssrc[] = {30, 31};
169
170 static const char kMediaStream1[] = "stream_1";
171 static const char kMediaStream2[] = "stream_2";
172 static const char kVideoTrack1[] = "video_1";
173 static const char kVideoTrack2[] = "video_2";
174 static const char kAudioTrack1[] = "audio_1";
175 static const char kAudioTrack2[] = "audio_2";
176 static const char kAudioTrack3[] = "audio_3";
177 static const char kDataTrack1[] = "data_1";
178 static const char kDataTrack2[] = "data_2";
179 static const char kDataTrack3[] = "data_3";
180
181 class MediaSessionDescriptionFactoryTest : public testing::Test {
182  public:
183   MediaSessionDescriptionFactoryTest()
184       : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
185     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
186     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
187     f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
188     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
189     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
190     f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
191     tdf1_.set_identity(&id1_);
192     tdf2_.set_identity(&id2_);
193   }
194
195
196   bool CompareCryptoParams(const CryptoParamsVec& c1,
197                            const CryptoParamsVec& c2) {
198     if (c1.size() != c2.size())
199       return false;
200     for (size_t i = 0; i < c1.size(); ++i)
201       if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
202           c1[i].key_params != c2[i].key_params ||
203           c1[i].session_params != c2[i].session_params)
204         return false;
205     return true;
206   }
207
208   void TestTransportInfo(bool offer, const MediaSessionOptions& options,
209                          bool has_current_desc) {
210     const std::string current_audio_ufrag = "current_audio_ufrag";
211     const std::string current_audio_pwd = "current_audio_pwd";
212     const std::string current_video_ufrag = "current_video_ufrag";
213     const std::string current_video_pwd = "current_video_pwd";
214     const std::string current_data_ufrag = "current_data_ufrag";
215     const std::string current_data_pwd = "current_data_pwd";
216     talk_base::scoped_ptr<SessionDescription> current_desc;
217     talk_base::scoped_ptr<SessionDescription> desc;
218     if (has_current_desc) {
219       current_desc.reset(new SessionDescription());
220       EXPECT_TRUE(current_desc->AddTransportInfo(
221           TransportInfo("audio",
222                         TransportDescription("",
223                                              current_audio_ufrag,
224                                              current_audio_pwd))));
225       EXPECT_TRUE(current_desc->AddTransportInfo(
226           TransportInfo("video",
227                         TransportDescription("",
228                                              current_video_ufrag,
229                                              current_video_pwd))));
230       EXPECT_TRUE(current_desc->AddTransportInfo(
231           TransportInfo("data",
232                         TransportDescription("",
233                                              current_data_ufrag,
234                                              current_data_pwd))));
235     }
236     if (offer) {
237       desc.reset(f1_.CreateOffer(options, current_desc.get()));
238     } else {
239       talk_base::scoped_ptr<SessionDescription> offer;
240       offer.reset(f1_.CreateOffer(options, NULL));
241       desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
242     }
243     ASSERT_TRUE(desc.get() != NULL);
244     const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
245     if (options.has_audio) {
246       EXPECT_TRUE(ti_audio != NULL);
247       if (has_current_desc) {
248         EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
249         EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
250       } else {
251         EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
252                   ti_audio->description.ice_ufrag.size());
253         EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
254                   ti_audio->description.ice_pwd.size());
255       }
256
257     } else {
258       EXPECT_TRUE(ti_audio == NULL);
259     }
260     const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
261     if (options.has_video) {
262       EXPECT_TRUE(ti_video != NULL);
263       if (options.bundle_enabled) {
264         EXPECT_EQ(ti_audio->description.ice_ufrag,
265                   ti_video->description.ice_ufrag);
266         EXPECT_EQ(ti_audio->description.ice_pwd,
267                   ti_video->description.ice_pwd);
268       } else {
269         if (has_current_desc) {
270           EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
271           EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
272         } else {
273           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
274                     ti_video->description.ice_ufrag.size());
275           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
276                     ti_video->description.ice_pwd.size());
277         }
278       }
279     } else {
280       EXPECT_TRUE(ti_video == NULL);
281     }
282     const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
283     if (options.has_data()) {
284       EXPECT_TRUE(ti_data != NULL);
285       if (options.bundle_enabled) {
286         EXPECT_EQ(ti_audio->description.ice_ufrag,
287                   ti_data->description.ice_ufrag);
288         EXPECT_EQ(ti_audio->description.ice_pwd,
289                   ti_data->description.ice_pwd);
290       } else {
291         if (has_current_desc) {
292           EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
293           EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
294         } else {
295           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
296                     ti_data->description.ice_ufrag.size());
297           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
298                     ti_data->description.ice_pwd.size());
299         }
300       }
301     } else {
302       EXPECT_TRUE(ti_video == NULL);
303     }
304   }
305
306   void TestCryptoWithBundle(bool offer) {
307     f1_.set_secure(SEC_ENABLED);
308     MediaSessionOptions options;
309     options.has_audio = true;
310     options.has_video = true;
311     options.data_channel_type = cricket::DCT_RTP;
312     talk_base::scoped_ptr<SessionDescription> ref_desc;
313     talk_base::scoped_ptr<SessionDescription> desc;
314     if (offer) {
315       options.bundle_enabled = false;
316       ref_desc.reset(f1_.CreateOffer(options, NULL));
317       options.bundle_enabled = true;
318       desc.reset(f1_.CreateOffer(options, ref_desc.get()));
319     } else {
320       options.bundle_enabled = true;
321       ref_desc.reset(f1_.CreateOffer(options, NULL));
322       desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
323     }
324     ASSERT_TRUE(desc.get() != NULL);
325     const cricket::MediaContentDescription* audio_media_desc =
326         static_cast<const cricket::MediaContentDescription*>(
327             desc.get()->GetContentDescriptionByName("audio"));
328     ASSERT_TRUE(audio_media_desc != NULL);
329     const cricket::MediaContentDescription* video_media_desc =
330         static_cast<const cricket::MediaContentDescription*>(
331             desc.get()->GetContentDescriptionByName("video"));
332     ASSERT_TRUE(video_media_desc != NULL);
333     EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
334                                     video_media_desc->cryptos()));
335     EXPECT_EQ(1u, audio_media_desc->cryptos().size());
336     EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
337               audio_media_desc->cryptos()[0].cipher_suite);
338
339     // Verify the selected crypto is one from the reference audio
340     // media content.
341     const cricket::MediaContentDescription* ref_audio_media_desc =
342         static_cast<const cricket::MediaContentDescription*>(
343             ref_desc.get()->GetContentDescriptionByName("audio"));
344     bool found = false;
345     for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
346       if (ref_audio_media_desc->cryptos()[i].Matches(
347           audio_media_desc->cryptos()[0])) {
348         found = true;
349         break;
350       }
351     }
352     EXPECT_TRUE(found);
353   }
354
355   // This test that the audio and video media direction is set to
356   // |expected_direction_in_answer| in an answer if the offer direction is set
357   // to |direction_in_offer|.
358   void TestMediaDirectionInAnswer(
359       cricket::MediaContentDirection direction_in_offer,
360       cricket::MediaContentDirection expected_direction_in_answer) {
361     MediaSessionOptions opts;
362     opts.has_video = true;
363     talk_base::scoped_ptr<SessionDescription> offer(
364         f1_.CreateOffer(opts, NULL));
365     ASSERT_TRUE(offer.get() != NULL);
366     ContentInfo* ac_offer= offer->GetContentByName("audio");
367     ASSERT_TRUE(ac_offer != NULL);
368     AudioContentDescription* acd_offer =
369         static_cast<AudioContentDescription*>(ac_offer->description);
370     acd_offer->set_direction(direction_in_offer);
371     ContentInfo* vc_offer= offer->GetContentByName("video");
372     ASSERT_TRUE(vc_offer != NULL);
373     VideoContentDescription* vcd_offer =
374         static_cast<VideoContentDescription*>(vc_offer->description);
375     vcd_offer->set_direction(direction_in_offer);
376
377     talk_base::scoped_ptr<SessionDescription> answer(
378         f2_.CreateAnswer(offer.get(), opts, NULL));
379     const AudioContentDescription* acd_answer =
380         GetFirstAudioContentDescription(answer.get());
381     EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
382     const VideoContentDescription* vcd_answer =
383         GetFirstVideoContentDescription(answer.get());
384     EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
385   }
386
387   bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
388     const cricket::ContentDescription* description = content->description;
389     ASSERT(description != NULL);
390     const cricket::AudioContentDescription* audio_content_desc =
391         static_cast<const cricket::AudioContentDescription*>(description);
392     ASSERT(audio_content_desc != NULL);
393     for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
394       if (audio_content_desc->codecs()[i].name == "CN")
395         return false;
396     }
397     return true;
398   }
399
400  protected:
401   MediaSessionDescriptionFactory f1_;
402   MediaSessionDescriptionFactory f2_;
403   TransportDescriptionFactory tdf1_;
404   TransportDescriptionFactory tdf2_;
405   talk_base::FakeSSLIdentity id1_;
406   talk_base::FakeSSLIdentity id2_;
407 };
408
409 // Create a typical audio offer, and ensure it matches what we expect.
410 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
411   f1_.set_secure(SEC_ENABLED);
412   talk_base::scoped_ptr<SessionDescription> offer(
413       f1_.CreateOffer(MediaSessionOptions(), NULL));
414   ASSERT_TRUE(offer.get() != NULL);
415   const ContentInfo* ac = offer->GetContentByName("audio");
416   const ContentInfo* vc = offer->GetContentByName("video");
417   ASSERT_TRUE(ac != NULL);
418   ASSERT_TRUE(vc == NULL);
419   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
420   const AudioContentDescription* acd =
421       static_cast<const AudioContentDescription*>(ac->description);
422   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
423   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
424   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
425   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
426   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
427   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
428   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
429 }
430
431 // Create a typical video offer, and ensure it matches what we expect.
432 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
433   MediaSessionOptions opts;
434   opts.has_video = true;
435   f1_.set_secure(SEC_ENABLED);
436   talk_base::scoped_ptr<SessionDescription>
437       offer(f1_.CreateOffer(opts, NULL));
438   ASSERT_TRUE(offer.get() != NULL);
439   const ContentInfo* ac = offer->GetContentByName("audio");
440   const ContentInfo* vc = offer->GetContentByName("video");
441   ASSERT_TRUE(ac != NULL);
442   ASSERT_TRUE(vc != NULL);
443   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
444   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
445   const AudioContentDescription* acd =
446       static_cast<const AudioContentDescription*>(ac->description);
447   const VideoContentDescription* vcd =
448       static_cast<const VideoContentDescription*>(vc->description);
449   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
450   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
451   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
452   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
453   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
454   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
455   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
456   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
457   EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
458   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
459   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
460   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
461   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
462   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
463 }
464
465 // Test creating an offer with bundle where the Codecs have the same dynamic
466 // RTP playlod type. The test verifies that the offer don't contain the
467 // duplicate RTP payload types.
468 TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
469   const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
470   const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
471   const DataCodec& offered_data_codec = f2_.data_codecs()[0];
472   ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
473   ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
474
475   MediaSessionOptions opts;
476   opts.has_audio = true;
477   opts.has_video = true;
478   opts.data_channel_type = cricket::DCT_RTP;
479   opts.bundle_enabled = true;
480   talk_base::scoped_ptr<SessionDescription>
481   offer(f2_.CreateOffer(opts, NULL));
482   const VideoContentDescription* vcd =
483       GetFirstVideoContentDescription(offer.get());
484   const AudioContentDescription* acd =
485       GetFirstAudioContentDescription(offer.get());
486   const DataContentDescription* dcd =
487       GetFirstDataContentDescription(offer.get());
488   ASSERT_TRUE(NULL != vcd);
489   ASSERT_TRUE(NULL != acd);
490   ASSERT_TRUE(NULL != dcd);
491   EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
492   EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
493   EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
494   EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
495   EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
496   EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
497 }
498
499 // Test creating an updated offer with with bundle, audio, video and data
500 // after an audio only session has been negotiated.
501 TEST_F(MediaSessionDescriptionFactoryTest,
502        TestCreateUpdatedVideoOfferWithBundle) {
503   f1_.set_secure(SEC_ENABLED);
504   f2_.set_secure(SEC_ENABLED);
505   MediaSessionOptions opts;
506   opts.has_audio = true;
507   opts.has_video = false;
508   opts.data_channel_type = cricket::DCT_NONE;
509   opts.bundle_enabled = true;
510   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
511   talk_base::scoped_ptr<SessionDescription> answer(
512       f2_.CreateAnswer(offer.get(), opts, NULL));
513
514   MediaSessionOptions updated_opts;
515   updated_opts.has_audio = true;
516   updated_opts.has_video = true;
517   updated_opts.data_channel_type = cricket::DCT_RTP;
518   updated_opts.bundle_enabled = true;
519   talk_base::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
520       updated_opts, answer.get()));
521
522   const AudioContentDescription* acd =
523       GetFirstAudioContentDescription(updated_offer.get());
524   const VideoContentDescription* vcd =
525       GetFirstVideoContentDescription(updated_offer.get());
526   const DataContentDescription* dcd =
527       GetFirstDataContentDescription(updated_offer.get());
528   EXPECT_TRUE(NULL != vcd);
529   EXPECT_TRUE(NULL != acd);
530   EXPECT_TRUE(NULL != dcd);
531
532   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
533   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
534   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
535   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
536   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
537   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
538 }
539 // Create a RTP data offer, and ensure it matches what we expect.
540 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
541   MediaSessionOptions opts;
542   opts.data_channel_type = cricket::DCT_RTP;
543   f1_.set_secure(SEC_ENABLED);
544   talk_base::scoped_ptr<SessionDescription>
545       offer(f1_.CreateOffer(opts, NULL));
546   ASSERT_TRUE(offer.get() != NULL);
547   const ContentInfo* ac = offer->GetContentByName("audio");
548   const ContentInfo* dc = offer->GetContentByName("data");
549   ASSERT_TRUE(ac != NULL);
550   ASSERT_TRUE(dc != NULL);
551   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
552   EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
553   const AudioContentDescription* acd =
554       static_cast<const AudioContentDescription*>(ac->description);
555   const DataContentDescription* dcd =
556       static_cast<const DataContentDescription*>(dc->description);
557   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
558   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
559   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
560   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
561   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
562   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
563   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
564   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
565   EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
566   EXPECT_NE(0U, dcd->first_ssrc());             // a random nonzero ssrc
567   EXPECT_EQ(cricket::kDataMaxBandwidth,
568             dcd->bandwidth());                  // default bandwidth (auto)
569   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
570   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
571   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
572 }
573
574 // Create an SCTP data offer with bundle without error.
575 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
576   MediaSessionOptions opts;
577   opts.has_audio = false;
578   opts.bundle_enabled = true;
579   opts.data_channel_type = cricket::DCT_SCTP;
580   f1_.set_secure(SEC_ENABLED);
581   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
582   EXPECT_TRUE(offer.get() != NULL);
583   EXPECT_TRUE(offer->GetContentByName("data") != NULL);
584 }
585
586 // Create an audio, video offer without legacy StreamParams.
587 TEST_F(MediaSessionDescriptionFactoryTest,
588        TestCreateOfferWithoutLegacyStreams) {
589   MediaSessionOptions opts;
590   opts.has_video = true;
591   f1_.set_add_legacy_streams(false);
592   talk_base::scoped_ptr<SessionDescription>
593       offer(f1_.CreateOffer(opts, NULL));
594   ASSERT_TRUE(offer.get() != NULL);
595   const ContentInfo* ac = offer->GetContentByName("audio");
596   const ContentInfo* vc = offer->GetContentByName("video");
597   ASSERT_TRUE(ac != NULL);
598   ASSERT_TRUE(vc != NULL);
599   const AudioContentDescription* acd =
600       static_cast<const AudioContentDescription*>(ac->description);
601   const VideoContentDescription* vcd =
602       static_cast<const VideoContentDescription*>(vc->description);
603
604   EXPECT_FALSE(vcd->has_ssrcs());             // No StreamParams.
605   EXPECT_FALSE(acd->has_ssrcs());             // No StreamParams.
606 }
607
608 // Create a typical audio answer, and ensure it matches what we expect.
609 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
610   f1_.set_secure(SEC_ENABLED);
611   f2_.set_secure(SEC_ENABLED);
612   talk_base::scoped_ptr<SessionDescription> offer(
613       f1_.CreateOffer(MediaSessionOptions(), NULL));
614   ASSERT_TRUE(offer.get() != NULL);
615   talk_base::scoped_ptr<SessionDescription> answer(
616       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
617   const ContentInfo* ac = answer->GetContentByName("audio");
618   const ContentInfo* vc = answer->GetContentByName("video");
619   ASSERT_TRUE(ac != NULL);
620   ASSERT_TRUE(vc == NULL);
621   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
622   const AudioContentDescription* acd =
623       static_cast<const AudioContentDescription*>(ac->description);
624   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
625   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
626   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
627   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
628   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
629   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
630   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
631 }
632
633 // Create a typical video answer, and ensure it matches what we expect.
634 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
635   MediaSessionOptions opts;
636   opts.has_video = true;
637   f1_.set_secure(SEC_ENABLED);
638   f2_.set_secure(SEC_ENABLED);
639   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
640   ASSERT_TRUE(offer.get() != NULL);
641   talk_base::scoped_ptr<SessionDescription> answer(
642       f2_.CreateAnswer(offer.get(), opts, NULL));
643   const ContentInfo* ac = answer->GetContentByName("audio");
644   const ContentInfo* vc = answer->GetContentByName("video");
645   ASSERT_TRUE(ac != NULL);
646   ASSERT_TRUE(vc != NULL);
647   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
648   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
649   const AudioContentDescription* acd =
650       static_cast<const AudioContentDescription*>(ac->description);
651   const VideoContentDescription* vcd =
652       static_cast<const VideoContentDescription*>(vc->description);
653   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
654   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
655   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
656   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
657   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
658   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
659   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
660   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
661   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
662   EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
663   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
664   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
665 }
666
667 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
668   MediaSessionOptions opts;
669   opts.data_channel_type = cricket::DCT_RTP;
670   f1_.set_secure(SEC_ENABLED);
671   f2_.set_secure(SEC_ENABLED);
672   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
673   ASSERT_TRUE(offer.get() != NULL);
674   talk_base::scoped_ptr<SessionDescription> answer(
675       f2_.CreateAnswer(offer.get(), opts, NULL));
676   const ContentInfo* ac = answer->GetContentByName("audio");
677   const ContentInfo* vc = answer->GetContentByName("data");
678   ASSERT_TRUE(ac != NULL);
679   ASSERT_TRUE(vc != NULL);
680   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
681   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
682   const AudioContentDescription* acd =
683       static_cast<const AudioContentDescription*>(ac->description);
684   const DataContentDescription* vcd =
685       static_cast<const DataContentDescription*>(vc->description);
686   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
687   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
688   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
689   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
690   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
691   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
692   EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
693   EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
694   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
695   EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
696   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
697   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
698 }
699
700 // This test that the media direction is set to send/receive in an answer if
701 // the offer is send receive.
702 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
703   TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
704 }
705
706 // This test that the media direction is set to receive only in an answer if
707 // the offer is send only.
708 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
709   TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
710 }
711
712 // This test that the media direction is set to send only in an answer if
713 // the offer is recv only.
714 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
715   TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
716 }
717
718 // This test that the media direction is set to inactive in an answer if
719 // the offer is inactive.
720 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
721   TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
722 }
723
724 // Test that a data content with an unknown protocol is rejected in an answer.
725 TEST_F(MediaSessionDescriptionFactoryTest,
726        CreateDataAnswerToOfferWithUnknownProtocol) {
727   MediaSessionOptions opts;
728   opts.data_channel_type = cricket::DCT_RTP;
729   opts.has_audio = false;
730   f1_.set_secure(SEC_ENABLED);
731   f2_.set_secure(SEC_ENABLED);
732   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
733   ContentInfo* dc_offer= offer->GetContentByName("data");
734   ASSERT_TRUE(dc_offer != NULL);
735   DataContentDescription* dcd_offer =
736       static_cast<DataContentDescription*>(dc_offer->description);
737   ASSERT_TRUE(dcd_offer != NULL);
738   std::string protocol = "a weird unknown protocol";
739   dcd_offer->set_protocol(protocol);
740
741   talk_base::scoped_ptr<SessionDescription> answer(
742       f2_.CreateAnswer(offer.get(), opts, NULL));
743
744   const ContentInfo* dc_answer = answer->GetContentByName("data");
745   ASSERT_TRUE(dc_answer != NULL);
746   EXPECT_TRUE(dc_answer->rejected);
747   const DataContentDescription* dcd_answer =
748       static_cast<const DataContentDescription*>(dc_answer->description);
749   ASSERT_TRUE(dcd_answer != NULL);
750   EXPECT_EQ(protocol, dcd_answer->protocol());
751 }
752
753 // Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
754 TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
755   MediaSessionOptions opts;
756   f1_.set_secure(SEC_DISABLED);
757   f2_.set_secure(SEC_DISABLED);
758   tdf1_.set_secure(SEC_DISABLED);
759   tdf2_.set_secure(SEC_DISABLED);
760
761   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
762   const AudioContentDescription* offer_acd =
763       GetFirstAudioContentDescription(offer.get());
764   ASSERT_TRUE(offer_acd != NULL);
765   EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
766
767   talk_base::scoped_ptr<SessionDescription> answer(
768       f2_.CreateAnswer(offer.get(), opts, NULL));
769
770   const ContentInfo* ac_answer = answer->GetContentByName("audio");
771   ASSERT_TRUE(ac_answer != NULL);
772   EXPECT_FALSE(ac_answer->rejected);
773
774   const AudioContentDescription* answer_acd =
775       GetFirstAudioContentDescription(answer.get());
776   ASSERT_TRUE(answer_acd != NULL);
777   EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
778 }
779
780 // Create a video offer and answer and ensure the RTP header extensions
781 // matches what we expect.
782 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
783   MediaSessionOptions opts;
784   opts.has_video = true;
785
786   f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
787   f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
788   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
789   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
790
791   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
792   ASSERT_TRUE(offer.get() != NULL);
793   talk_base::scoped_ptr<SessionDescription> answer(
794       f2_.CreateAnswer(offer.get(), opts, NULL));
795
796   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
797             GetFirstAudioContentDescription(
798                 offer.get())->rtp_header_extensions());
799   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
800             GetFirstVideoContentDescription(
801                 offer.get())->rtp_header_extensions());
802   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
803             GetFirstAudioContentDescription(
804                 answer.get())->rtp_header_extensions());
805   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
806             GetFirstVideoContentDescription(
807                 answer.get())->rtp_header_extensions());
808 }
809
810 // Create an audio, video, data answer without legacy StreamParams.
811 TEST_F(MediaSessionDescriptionFactoryTest,
812        TestCreateAnswerWithoutLegacyStreams) {
813   MediaSessionOptions opts;
814   opts.has_video = true;
815   opts.data_channel_type = cricket::DCT_RTP;
816   f1_.set_add_legacy_streams(false);
817   f2_.set_add_legacy_streams(false);
818   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
819   ASSERT_TRUE(offer.get() != NULL);
820   talk_base::scoped_ptr<SessionDescription> answer(
821       f2_.CreateAnswer(offer.get(), opts, NULL));
822   const ContentInfo* ac = answer->GetContentByName("audio");
823   const ContentInfo* vc = answer->GetContentByName("video");
824   const ContentInfo* dc = answer->GetContentByName("data");
825   ASSERT_TRUE(ac != NULL);
826   ASSERT_TRUE(vc != NULL);
827   const AudioContentDescription* acd =
828       static_cast<const AudioContentDescription*>(ac->description);
829   const VideoContentDescription* vcd =
830       static_cast<const VideoContentDescription*>(vc->description);
831   const DataContentDescription* dcd =
832       static_cast<const DataContentDescription*>(dc->description);
833
834   EXPECT_FALSE(acd->has_ssrcs());  // No StreamParams.
835   EXPECT_FALSE(vcd->has_ssrcs());  // No StreamParams.
836   EXPECT_FALSE(dcd->has_ssrcs());  // No StreamParams.
837 }
838
839 TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
840   MediaSessionOptions opts;
841   opts.has_video = true;
842   opts.data_channel_type = cricket::DCT_RTP;
843   f1_.set_secure(SEC_ENABLED);
844   talk_base::scoped_ptr<SessionDescription>
845       offer(f1_.CreateOffer(opts, NULL));
846   ASSERT_TRUE(offer.get() != NULL);
847   const ContentInfo* ac = offer->GetContentByName("audio");
848   const ContentInfo* vc = offer->GetContentByName("video");
849   const ContentInfo* dc = offer->GetContentByName("data");
850   AudioContentDescription* acd = const_cast<AudioContentDescription*>(
851       static_cast<const AudioContentDescription*>(ac->description));
852   VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
853       static_cast<const VideoContentDescription*>(vc->description));
854   DataContentDescription* dcd = const_cast<DataContentDescription*>(
855       static_cast<const DataContentDescription*>(dc->description));
856
857   EXPECT_FALSE(acd->partial());  // default is false.
858   acd->set_partial(true);
859   EXPECT_TRUE(acd->partial());
860   acd->set_partial(false);
861   EXPECT_FALSE(acd->partial());
862
863   EXPECT_FALSE(vcd->partial());  // default is false.
864   vcd->set_partial(true);
865   EXPECT_TRUE(vcd->partial());
866   vcd->set_partial(false);
867   EXPECT_FALSE(vcd->partial());
868
869   EXPECT_FALSE(dcd->partial());  // default is false.
870   dcd->set_partial(true);
871   EXPECT_TRUE(dcd->partial());
872   dcd->set_partial(false);
873   EXPECT_FALSE(dcd->partial());
874 }
875
876 // Create a typical video answer, and ensure it matches what we expect.
877 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
878   MediaSessionOptions offer_opts;
879   MediaSessionOptions answer_opts;
880   answer_opts.has_video = true;
881   offer_opts.has_video = true;
882   answer_opts.data_channel_type = cricket::DCT_RTP;
883   offer_opts.data_channel_type = cricket::DCT_RTP;
884
885   talk_base::scoped_ptr<SessionDescription> offer;
886   talk_base::scoped_ptr<SessionDescription> answer;
887
888   offer_opts.rtcp_mux_enabled = true;
889   answer_opts.rtcp_mux_enabled = true;
890
891   offer.reset(f1_.CreateOffer(offer_opts, NULL));
892   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
893   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
894   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
895   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
896   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
897   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
898   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
899   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
900   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
901   EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
902   EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
903   EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
904   EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
905
906   offer_opts.rtcp_mux_enabled = true;
907   answer_opts.rtcp_mux_enabled = false;
908
909   offer.reset(f1_.CreateOffer(offer_opts, NULL));
910   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
911   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
912   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
913   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
914   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
915   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
916   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
917   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
918   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
919   EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
920   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
921   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
922   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
923
924   offer_opts.rtcp_mux_enabled = false;
925   answer_opts.rtcp_mux_enabled = true;
926
927   offer.reset(f1_.CreateOffer(offer_opts, NULL));
928   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
929   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
930   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
931   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
932   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
933   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
934   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
935   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
936   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
937   EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
938   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
939   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
940   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
941
942   offer_opts.rtcp_mux_enabled = false;
943   answer_opts.rtcp_mux_enabled = false;
944
945   offer.reset(f1_.CreateOffer(offer_opts, NULL));
946   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
947   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
948   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
949   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
950   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
951   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
952   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
953   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
954   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
955   EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
956   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
957   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
958   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
959 }
960
961 // Create an audio-only answer to a video offer.
962 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
963   MediaSessionOptions opts;
964   opts.has_video = true;
965   talk_base::scoped_ptr<SessionDescription>
966       offer(f1_.CreateOffer(opts, NULL));
967   ASSERT_TRUE(offer.get() != NULL);
968   talk_base::scoped_ptr<SessionDescription> answer(
969       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
970   const ContentInfo* ac = answer->GetContentByName("audio");
971   const ContentInfo* vc = answer->GetContentByName("video");
972   ASSERT_TRUE(ac != NULL);
973   ASSERT_TRUE(vc != NULL);
974   ASSERT_TRUE(vc->description != NULL);
975   EXPECT_TRUE(vc->rejected);
976 }
977
978 // Create an audio-only answer to an offer with data.
979 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
980   MediaSessionOptions opts;
981   opts.data_channel_type = cricket::DCT_RTP;
982   talk_base::scoped_ptr<SessionDescription>
983       offer(f1_.CreateOffer(opts, NULL));
984   ASSERT_TRUE(offer.get() != NULL);
985   talk_base::scoped_ptr<SessionDescription> answer(
986       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
987   const ContentInfo* ac = answer->GetContentByName("audio");
988   const ContentInfo* dc = answer->GetContentByName("data");
989   ASSERT_TRUE(ac != NULL);
990   ASSERT_TRUE(dc != NULL);
991   ASSERT_TRUE(dc->description != NULL);
992   EXPECT_TRUE(dc->rejected);
993 }
994
995 // Create an answer that rejects the contents which are rejected in the offer.
996 TEST_F(MediaSessionDescriptionFactoryTest,
997        CreateAnswerToOfferWithRejectedMedia) {
998   MediaSessionOptions opts;
999   opts.has_video = true;
1000   opts.data_channel_type = cricket::DCT_RTP;
1001   talk_base::scoped_ptr<SessionDescription>
1002       offer(f1_.CreateOffer(opts, NULL));
1003   ASSERT_TRUE(offer.get() != NULL);
1004   ContentInfo* ac = offer->GetContentByName("audio");
1005   ContentInfo* vc = offer->GetContentByName("video");
1006   ContentInfo* dc = offer->GetContentByName("data");
1007   ASSERT_TRUE(ac != NULL);
1008   ASSERT_TRUE(vc != NULL);
1009   ASSERT_TRUE(dc != NULL);
1010   ac->rejected = true;
1011   vc->rejected = true;
1012   dc->rejected = true;
1013   talk_base::scoped_ptr<SessionDescription> answer(
1014       f2_.CreateAnswer(offer.get(), opts, NULL));
1015   ac = answer->GetContentByName("audio");
1016   vc = answer->GetContentByName("video");
1017   dc = answer->GetContentByName("data");
1018   ASSERT_TRUE(ac != NULL);
1019   ASSERT_TRUE(vc != NULL);
1020   ASSERT_TRUE(dc != NULL);
1021   EXPECT_TRUE(ac->rejected);
1022   EXPECT_TRUE(vc->rejected);
1023   EXPECT_TRUE(dc->rejected);
1024 }
1025
1026 // Create an audio and video offer with:
1027 // - one video track
1028 // - two audio tracks
1029 // - two data tracks
1030 // and ensure it matches what we expect. Also updates the initial offer by
1031 // adding a new video track and replaces one of the audio tracks.
1032 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1033   MediaSessionOptions opts;
1034   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1035   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1036   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1037   opts.data_channel_type = cricket::DCT_RTP;
1038   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1039   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1040
1041   f1_.set_secure(SEC_ENABLED);
1042   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1043
1044   ASSERT_TRUE(offer.get() != NULL);
1045   const ContentInfo* ac = offer->GetContentByName("audio");
1046   const ContentInfo* vc = offer->GetContentByName("video");
1047   const ContentInfo* dc = offer->GetContentByName("data");
1048   ASSERT_TRUE(ac != NULL);
1049   ASSERT_TRUE(vc != NULL);
1050   ASSERT_TRUE(dc != NULL);
1051   const AudioContentDescription* acd =
1052       static_cast<const AudioContentDescription*>(ac->description);
1053   const VideoContentDescription* vcd =
1054       static_cast<const VideoContentDescription*>(vc->description);
1055   const DataContentDescription* dcd =
1056       static_cast<const DataContentDescription*>(dc->description);
1057   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1058   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1059
1060   const StreamParamsVec& audio_streams = acd->streams();
1061   ASSERT_EQ(2U, audio_streams.size());
1062   EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1063   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1064   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1065   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1066   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1067   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1068   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1069
1070   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
1071   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
1072   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1073
1074   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1075   EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1076   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1077
1078   const StreamParamsVec& video_streams = vcd->streams();
1079   ASSERT_EQ(1U, video_streams.size());
1080   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1081   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1082   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
1083   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
1084
1085   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1086   EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1087   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1088
1089   const StreamParamsVec& data_streams = dcd->streams();
1090   ASSERT_EQ(2U, data_streams.size());
1091   EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1092   EXPECT_EQ(kDataTrack1, data_streams[0].id);
1093   ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1094   EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1095   EXPECT_EQ(kDataTrack2, data_streams[1].id);
1096   ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1097   EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1098
1099   EXPECT_EQ(cricket::kDataMaxBandwidth,
1100             dcd->bandwidth());                  // default bandwidth (auto)
1101   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
1102   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1103
1104
1105   // Update the offer. Add a new video track that is not synched to the
1106   // other tracks and replace audio track 2 with audio track 3.
1107   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1108   opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1109   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1110   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
1111   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
1112   talk_base::scoped_ptr<SessionDescription>
1113       updated_offer(f1_.CreateOffer(opts, offer.get()));
1114
1115   ASSERT_TRUE(updated_offer.get() != NULL);
1116   ac = updated_offer->GetContentByName("audio");
1117   vc = updated_offer->GetContentByName("video");
1118   dc = updated_offer->GetContentByName("data");
1119   ASSERT_TRUE(ac != NULL);
1120   ASSERT_TRUE(vc != NULL);
1121   ASSERT_TRUE(dc != NULL);
1122   const AudioContentDescription* updated_acd =
1123       static_cast<const AudioContentDescription*>(ac->description);
1124   const VideoContentDescription* updated_vcd =
1125       static_cast<const VideoContentDescription*>(vc->description);
1126   const DataContentDescription* updated_dcd =
1127       static_cast<const DataContentDescription*>(dc->description);
1128
1129   EXPECT_EQ(acd->type(), updated_acd->type());
1130   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1131   EXPECT_EQ(vcd->type(), updated_vcd->type());
1132   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1133   EXPECT_EQ(dcd->type(), updated_dcd->type());
1134   EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1135   ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1136   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1137   ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1138   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1139   ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1140   EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1141
1142   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1143   ASSERT_EQ(2U, updated_audio_streams.size());
1144   EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1145   EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id);  // New audio track.
1146   ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1147   EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1148   EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1149
1150   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1151   ASSERT_EQ(2U, updated_video_streams.size());
1152   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1153   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1154   EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1155
1156   const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1157   ASSERT_EQ(2U, updated_data_streams.size());
1158   EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1159   EXPECT_EQ(kDataTrack3, updated_data_streams[1].id);  // New data track.
1160   ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1161   EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1162   EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1163 }
1164
1165 // Create an offer with simulcast video stream.
1166 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1167   MediaSessionOptions opts;
1168   const int num_sim_layers = 3;
1169   opts.AddVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
1170   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1171
1172   ASSERT_TRUE(offer.get() != NULL);
1173   const ContentInfo* vc = offer->GetContentByName("video");
1174   ASSERT_TRUE(vc != NULL);
1175   const VideoContentDescription* vcd =
1176       static_cast<const VideoContentDescription*>(vc->description);
1177
1178   const StreamParamsVec& video_streams = vcd->streams();
1179   ASSERT_EQ(1U, video_streams.size());
1180   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1181   const SsrcGroup* sim_ssrc_group =
1182       video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1183   ASSERT_TRUE(sim_ssrc_group != NULL);
1184   EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1185 }
1186
1187 // Create an audio and video answer to a standard video offer with:
1188 // - one video track
1189 // - two audio tracks
1190 // - two data tracks
1191 // and ensure it matches what we expect. Also updates the initial answer by
1192 // adding a new video track and removes one of the audio tracks.
1193 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1194   MediaSessionOptions offer_opts;
1195   offer_opts.has_video = true;
1196   offer_opts.data_channel_type = cricket::DCT_RTP;
1197   f1_.set_secure(SEC_ENABLED);
1198   f2_.set_secure(SEC_ENABLED);
1199   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
1200                                                                   NULL));
1201
1202   MediaSessionOptions opts;
1203   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1204   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1205   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1206   opts.data_channel_type = cricket::DCT_RTP;
1207   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1208   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1209
1210   talk_base::scoped_ptr<SessionDescription>
1211       answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1212
1213   ASSERT_TRUE(answer.get() != NULL);
1214   const ContentInfo* ac = answer->GetContentByName("audio");
1215   const ContentInfo* vc = answer->GetContentByName("video");
1216   const ContentInfo* dc = answer->GetContentByName("data");
1217   ASSERT_TRUE(ac != NULL);
1218   ASSERT_TRUE(vc != NULL);
1219   ASSERT_TRUE(dc != NULL);
1220   const AudioContentDescription* acd =
1221       static_cast<const AudioContentDescription*>(ac->description);
1222   const VideoContentDescription* vcd =
1223       static_cast<const VideoContentDescription*>(vc->description);
1224   const DataContentDescription* dcd =
1225       static_cast<const DataContentDescription*>(dc->description);
1226   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1227   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1228   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1229
1230   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1231   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1232
1233   const StreamParamsVec& audio_streams = acd->streams();
1234   ASSERT_EQ(2U, audio_streams.size());
1235   EXPECT_TRUE(audio_streams[0].cname ==  audio_streams[1].cname);
1236   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1237   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1238   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1239   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1240   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1241   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1242
1243   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
1244   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
1245
1246   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1247   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1248
1249   const StreamParamsVec& video_streams = vcd->streams();
1250   ASSERT_EQ(1U, video_streams.size());
1251   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1252   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1253   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
1254   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
1255
1256   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1257   EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1258
1259   const StreamParamsVec& data_streams = dcd->streams();
1260   ASSERT_EQ(2U, data_streams.size());
1261   EXPECT_TRUE(data_streams[0].cname ==  data_streams[1].cname);
1262   EXPECT_EQ(kDataTrack1, data_streams[0].id);
1263   ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1264   EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1265   EXPECT_EQ(kDataTrack2, data_streams[1].id);
1266   ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1267   EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1268
1269   EXPECT_EQ(cricket::kDataMaxBandwidth,
1270             dcd->bandwidth());                  // default bandwidth (auto)
1271   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
1272
1273   // Update the answer. Add a new video track that is not synched to the
1274   // other traacks and remove 1 audio track.
1275   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1276   opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1277   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
1278   talk_base::scoped_ptr<SessionDescription>
1279       updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1280
1281   ASSERT_TRUE(updated_answer.get() != NULL);
1282   ac = updated_answer->GetContentByName("audio");
1283   vc = updated_answer->GetContentByName("video");
1284   dc = updated_answer->GetContentByName("data");
1285   ASSERT_TRUE(ac != NULL);
1286   ASSERT_TRUE(vc != NULL);
1287   ASSERT_TRUE(dc != NULL);
1288   const AudioContentDescription* updated_acd =
1289       static_cast<const AudioContentDescription*>(ac->description);
1290   const VideoContentDescription* updated_vcd =
1291       static_cast<const VideoContentDescription*>(vc->description);
1292   const DataContentDescription* updated_dcd =
1293       static_cast<const DataContentDescription*>(dc->description);
1294
1295   ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1296   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1297   ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1298   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1299   ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1300   EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1301
1302   EXPECT_EQ(acd->type(), updated_acd->type());
1303   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1304   EXPECT_EQ(vcd->type(), updated_vcd->type());
1305   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1306   EXPECT_EQ(dcd->type(), updated_dcd->type());
1307   EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1308
1309   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1310   ASSERT_EQ(1U, updated_audio_streams.size());
1311   EXPECT_TRUE(audio_streams[0] ==  updated_audio_streams[0]);
1312
1313   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1314   ASSERT_EQ(2U, updated_video_streams.size());
1315   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1316   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1317   EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1318
1319   const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1320   ASSERT_EQ(1U, updated_data_streams.size());
1321   EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1322 }
1323
1324
1325 // Create an updated offer after creating an answer to the original offer and
1326 // verify that the codecs that were part of the original answer are not changed
1327 // in the updated offer.
1328 TEST_F(MediaSessionDescriptionFactoryTest,
1329        RespondentCreatesOfferAfterCreatingAnswer) {
1330   MediaSessionOptions opts;
1331   opts.has_audio = true;
1332   opts.has_video = true;
1333
1334   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1335   talk_base::scoped_ptr<SessionDescription> answer(
1336       f2_.CreateAnswer(offer.get(), opts, NULL));
1337
1338   const AudioContentDescription* acd =
1339       GetFirstAudioContentDescription(answer.get());
1340   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1341
1342   const VideoContentDescription* vcd =
1343       GetFirstVideoContentDescription(answer.get());
1344   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1345
1346   talk_base::scoped_ptr<SessionDescription> updated_offer(
1347       f2_.CreateOffer(opts, answer.get()));
1348
1349   // The expected audio codecs are the common audio codecs from the first
1350   // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1351   // preference order.
1352   const AudioCodec kUpdatedAudioCodecOffer[] = {
1353     kAudioCodecs2[0],
1354     kAudioCodecsAnswer[0],
1355     kAudioCodecsAnswer[1],
1356   };
1357
1358   // The expected video codecs are the common video codecs from the first
1359   // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1360   // preference order.
1361   const VideoCodec kUpdatedVideoCodecOffer[] = {
1362     kVideoCodecsAnswer[0],
1363     kVideoCodecs2[1],
1364   };
1365
1366   const AudioContentDescription* updated_acd =
1367       GetFirstAudioContentDescription(updated_offer.get());
1368   EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1369
1370   const VideoContentDescription* updated_vcd =
1371       GetFirstVideoContentDescription(updated_offer.get());
1372   EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1373 }
1374
1375 // Create an updated offer after creating an answer to the original offer and
1376 // verify that the codecs that were part of the original answer are not changed
1377 // in the updated offer. In this test Rtx is enabled.
1378 TEST_F(MediaSessionDescriptionFactoryTest,
1379        RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1380   MediaSessionOptions opts;
1381   opts.has_video = true;
1382   opts.has_audio = false;
1383   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1384   VideoCodec rtx_f1;
1385   rtx_f1.id = 126;
1386   rtx_f1.name = cricket::kRtxCodecName;
1387
1388   // This creates rtx for H264 with the payload type |f1_| uses.
1389   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
1390       talk_base::ToString<int>(kVideoCodecs1[1].id);
1391   f1_codecs.push_back(rtx_f1);
1392   f1_.set_video_codecs(f1_codecs);
1393
1394   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1395   VideoCodec rtx_f2;
1396   rtx_f2.id = 127;
1397   rtx_f2.name = cricket::kRtxCodecName;
1398
1399   // This creates rtx for H264 with the payload type |f2_| uses.
1400   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
1401       talk_base::ToString<int>(kVideoCodecs2[0].id);
1402   f2_codecs.push_back(rtx_f2);
1403   f2_.set_video_codecs(f2_codecs);
1404
1405   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1406   ASSERT_TRUE(offer.get() != NULL);
1407   talk_base::scoped_ptr<SessionDescription> answer(
1408       f2_.CreateAnswer(offer.get(), opts, NULL));
1409
1410   const VideoContentDescription* vcd =
1411       GetFirstVideoContentDescription(answer.get());
1412
1413   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1414   expected_codecs.push_back(rtx_f1);
1415
1416   EXPECT_EQ(expected_codecs, vcd->codecs());
1417
1418   // Now, make sure we get same result, except for the preference order,
1419   // if |f2_| creates an updated offer even though the default payload types
1420   // are different from |f1_|.
1421   expected_codecs[0].preference = f1_codecs[1].preference;
1422
1423   talk_base::scoped_ptr<SessionDescription> updated_offer(
1424       f2_.CreateOffer(opts, answer.get()));
1425   ASSERT_TRUE(updated_offer);
1426   talk_base::scoped_ptr<SessionDescription> updated_answer(
1427       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1428
1429   const VideoContentDescription* updated_vcd =
1430       GetFirstVideoContentDescription(updated_answer.get());
1431
1432   EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1433 }
1434
1435 // Create an updated offer that adds video after creating an audio only answer
1436 // to the original offer. This test verifies that if a video codec and the RTX
1437 // codec have the same default payload type as an audio codec that is already in
1438 // use, the added codecs payload types are changed.
1439 TEST_F(MediaSessionDescriptionFactoryTest,
1440        RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1441   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1442   VideoCodec rtx_f1;
1443   rtx_f1.id = 126;
1444   rtx_f1.name = cricket::kRtxCodecName;
1445
1446   // This creates rtx for H264 with the payload type |f1_| uses.
1447   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
1448       talk_base::ToString<int>(kVideoCodecs1[1].id);
1449   f1_codecs.push_back(rtx_f1);
1450   f1_.set_video_codecs(f1_codecs);
1451
1452   MediaSessionOptions opts;
1453   opts.has_audio = true;
1454   opts.has_video = false;
1455
1456   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1457   talk_base::scoped_ptr<SessionDescription> answer(
1458       f2_.CreateAnswer(offer.get(), opts, NULL));
1459
1460   const AudioContentDescription* acd =
1461       GetFirstAudioContentDescription(answer.get());
1462   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1463
1464   // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1465   // reference  be the same as an audio codec that was negotiated in the
1466   // first offer/answer exchange.
1467   opts.has_audio = true;
1468   opts.has_video = true;
1469
1470   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1471   int used_pl_type = acd->codecs()[0].id;
1472   f2_codecs[0].id = used_pl_type;  // Set the payload type for H264.
1473   VideoCodec rtx_f2;
1474   rtx_f2.id = 127;
1475   rtx_f2.name = cricket::kRtxCodecName;
1476   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
1477       talk_base::ToString<int>(used_pl_type);
1478   f2_codecs.push_back(rtx_f2);
1479   f2_.set_video_codecs(f2_codecs);
1480
1481   talk_base::scoped_ptr<SessionDescription> updated_offer(
1482       f2_.CreateOffer(opts, answer.get()));
1483   ASSERT_TRUE(updated_offer);
1484   talk_base::scoped_ptr<SessionDescription> updated_answer(
1485       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1486
1487   const AudioContentDescription* updated_acd =
1488       GetFirstAudioContentDescription(answer.get());
1489   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1490
1491   const VideoContentDescription* updated_vcd =
1492       GetFirstVideoContentDescription(updated_answer.get());
1493
1494   ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
1495   ASSERT_EQ(cricket::kRtxCodecName, updated_vcd->codecs()[1].name);
1496   int new_h264_pl_type =  updated_vcd->codecs()[0].id;
1497   EXPECT_NE(used_pl_type, new_h264_pl_type);
1498   VideoCodec rtx = updated_vcd->codecs()[1];
1499   int pt_referenced_by_rtx = talk_base::FromString<int>(
1500       rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1501   EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1502 }
1503
1504 // Test that RTX is ignored when there is no associated payload type parameter.
1505 TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1506   MediaSessionOptions opts;
1507   opts.has_video = true;
1508   opts.has_audio = false;
1509   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1510   VideoCodec rtx_f1;
1511   rtx_f1.id = 126;
1512   rtx_f1.name = cricket::kRtxCodecName;
1513
1514   f1_codecs.push_back(rtx_f1);
1515   f1_.set_video_codecs(f1_codecs);
1516
1517   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1518   VideoCodec rtx_f2;
1519   rtx_f2.id = 127;
1520   rtx_f2.name = cricket::kRtxCodecName;
1521
1522   // This creates rtx for H264 with the payload type |f2_| uses.
1523   rtx_f2.SetParam(cricket::kCodecParamAssociatedPayloadType,
1524                   talk_base::ToString<int>(kVideoCodecs2[0].id));
1525   f2_codecs.push_back(rtx_f2);
1526   f2_.set_video_codecs(f2_codecs);
1527
1528   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1529   ASSERT_TRUE(offer.get() != NULL);
1530   // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1531   // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1532   // is possible to test that that RTX is dropped when
1533   // kCodecParamAssociatedPayloadType is missing in the offer.
1534   VideoContentDescription* desc =
1535       static_cast<cricket::VideoContentDescription*>(
1536           offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1537   ASSERT_TRUE(desc != NULL);
1538   std::vector<VideoCodec> codecs = desc->codecs();
1539   for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1540        iter != codecs.end(); ++iter) {
1541     if (iter->name.find(cricket::kRtxCodecName) == 0) {
1542       iter->params.clear();
1543     }
1544   }
1545   desc->set_codecs(codecs);
1546
1547   talk_base::scoped_ptr<SessionDescription> answer(
1548       f2_.CreateAnswer(offer.get(), opts, NULL));
1549
1550   const VideoContentDescription* vcd =
1551       GetFirstVideoContentDescription(answer.get());
1552
1553   for (std::vector<VideoCodec>::const_iterator iter = vcd->codecs().begin();
1554        iter != vcd->codecs().end(); ++iter) {
1555     ASSERT_STRNE(iter->name.c_str(), cricket::kRtxCodecName);
1556   }
1557 }
1558
1559 // Create an updated offer after creating an answer to the original offer and
1560 // verify that the RTP header extensions that were part of the original answer
1561 // are not changed in the updated offer.
1562 TEST_F(MediaSessionDescriptionFactoryTest,
1563        RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1564   MediaSessionOptions opts;
1565   opts.has_audio = true;
1566   opts.has_video = true;
1567
1568   f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1569   f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1570   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1571   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1572
1573   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1574   talk_base::scoped_ptr<SessionDescription> answer(
1575       f2_.CreateAnswer(offer.get(), opts, NULL));
1576
1577   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1578             GetFirstAudioContentDescription(
1579                 answer.get())->rtp_header_extensions());
1580   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1581             GetFirstVideoContentDescription(
1582                 answer.get())->rtp_header_extensions());
1583
1584   talk_base::scoped_ptr<SessionDescription> updated_offer(
1585       f2_.CreateOffer(opts, answer.get()));
1586
1587   // The expected RTP header extensions in the new offer are the resulting
1588   // extensions from the first offer/answer exchange plus the extensions only
1589   // |f2_| offer.
1590   // Since the default local extension id |f2_| uses has already been used by
1591   // |f1_| for another extensions, it is changed to 255.
1592   const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1593     kAudioRtpExtensionAnswer[0],
1594     RtpHeaderExtension(kAudioRtpExtension2[1].uri, 255),
1595   };
1596
1597   // Since the default local extension id |f2_| uses has already been used by
1598   // |f1_| for another extensions, is is changed to 254.
1599   const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1600     kVideoRtpExtensionAnswer[0],
1601     RtpHeaderExtension(kVideoRtpExtension2[1].uri, 254),
1602   };
1603
1604   const AudioContentDescription* updated_acd =
1605       GetFirstAudioContentDescription(updated_offer.get());
1606   EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1607             updated_acd->rtp_header_extensions());
1608
1609   const VideoContentDescription* updated_vcd =
1610       GetFirstVideoContentDescription(updated_offer.get());
1611   EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1612             updated_vcd->rtp_header_extensions());
1613 }
1614
1615 TEST(MediaSessionDescription, CopySessionDescription) {
1616   SessionDescription source;
1617   cricket::ContentGroup group(cricket::CN_AUDIO);
1618   source.AddGroup(group);
1619   AudioContentDescription* acd(new AudioContentDescription());
1620   acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1621   acd->AddLegacyStream(1);
1622   source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1623   VideoContentDescription* vcd(new VideoContentDescription());
1624   vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1625   vcd->AddLegacyStream(2);
1626   source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1627
1628   talk_base::scoped_ptr<SessionDescription> copy(source.Copy());
1629   ASSERT_TRUE(copy.get() != NULL);
1630   EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1631   const ContentInfo* ac = copy->GetContentByName("audio");
1632   const ContentInfo* vc = copy->GetContentByName("video");
1633   ASSERT_TRUE(ac != NULL);
1634   ASSERT_TRUE(vc != NULL);
1635   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1636   const AudioContentDescription* acd_copy =
1637       static_cast<const AudioContentDescription*>(ac->description);
1638   EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1639   EXPECT_EQ(1u, acd->first_ssrc());
1640
1641   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1642   const VideoContentDescription* vcd_copy =
1643       static_cast<const VideoContentDescription*>(vc->description);
1644   EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1645   EXPECT_EQ(2u, vcd->first_ssrc());
1646 }
1647
1648 // The below TestTransportInfoXXX tests create different offers/answers, and
1649 // ensure the TransportInfo in the SessionDescription matches what we expect.
1650 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1651   MediaSessionOptions options;
1652   options.has_audio = true;
1653   TestTransportInfo(true, options, false);
1654 }
1655
1656 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1657   MediaSessionOptions options;
1658   options.has_audio = true;
1659   TestTransportInfo(true, options, true);
1660 }
1661
1662 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1663   MediaSessionOptions options;
1664   options.has_audio = true;
1665   options.has_video = true;
1666   options.data_channel_type = cricket::DCT_RTP;
1667   TestTransportInfo(true, options, false);
1668 }
1669
1670 TEST_F(MediaSessionDescriptionFactoryTest,
1671     TestTransportInfoOfferMultimediaCurrent) {
1672   MediaSessionOptions options;
1673   options.has_audio = true;
1674   options.has_video = true;
1675   options.data_channel_type = cricket::DCT_RTP;
1676   TestTransportInfo(true, options, true);
1677 }
1678
1679 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1680   MediaSessionOptions options;
1681   options.has_audio = true;
1682   options.has_video = true;
1683   options.data_channel_type = cricket::DCT_RTP;
1684   options.bundle_enabled = true;
1685   TestTransportInfo(true, options, false);
1686 }
1687
1688 TEST_F(MediaSessionDescriptionFactoryTest,
1689        TestTransportInfoOfferBundleCurrent) {
1690   MediaSessionOptions options;
1691   options.has_audio = true;
1692   options.has_video = true;
1693   options.data_channel_type = cricket::DCT_RTP;
1694   options.bundle_enabled = true;
1695   TestTransportInfo(true, options, true);
1696 }
1697
1698 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
1699   MediaSessionOptions options;
1700   options.has_audio = true;
1701   TestTransportInfo(false, options, false);
1702 }
1703
1704 TEST_F(MediaSessionDescriptionFactoryTest,
1705     TestTransportInfoAnswerAudioCurrent) {
1706   MediaSessionOptions options;
1707   options.has_audio = true;
1708   TestTransportInfo(false, options, true);
1709 }
1710
1711 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
1712   MediaSessionOptions options;
1713   options.has_audio = true;
1714   options.has_video = true;
1715   options.data_channel_type = cricket::DCT_RTP;
1716   TestTransportInfo(false, options, false);
1717 }
1718
1719 TEST_F(MediaSessionDescriptionFactoryTest,
1720     TestTransportInfoAnswerMultimediaCurrent) {
1721   MediaSessionOptions options;
1722   options.has_audio = true;
1723   options.has_video = true;
1724   options.data_channel_type = cricket::DCT_RTP;
1725   TestTransportInfo(false, options, true);
1726 }
1727
1728 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
1729   MediaSessionOptions options;
1730   options.has_audio = true;
1731   options.has_video = true;
1732   options.data_channel_type = cricket::DCT_RTP;
1733   options.bundle_enabled = true;
1734   TestTransportInfo(false, options, false);
1735 }
1736
1737 TEST_F(MediaSessionDescriptionFactoryTest,
1738     TestTransportInfoAnswerBundleCurrent) {
1739   MediaSessionOptions options;
1740   options.has_audio = true;
1741   options.has_video = true;
1742   options.data_channel_type = cricket::DCT_RTP;
1743   options.bundle_enabled = true;
1744   TestTransportInfo(false, options, true);
1745 }
1746
1747 // Create an offer with bundle enabled and verify the crypto parameters are
1748 // the common set of the available cryptos.
1749 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
1750   TestCryptoWithBundle(true);
1751 }
1752
1753 // Create an answer with bundle enabled and verify the crypto parameters are
1754 // the common set of the available cryptos.
1755 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
1756   TestCryptoWithBundle(false);
1757 }
1758
1759 // Test that we include both SDES and DTLS in the offer, but only include SDES
1760 // in the answer if DTLS isn't negotiated.
1761 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
1762   f1_.set_secure(SEC_ENABLED);
1763   f2_.set_secure(SEC_ENABLED);
1764   tdf1_.set_secure(SEC_ENABLED);
1765   tdf2_.set_secure(SEC_DISABLED);
1766   MediaSessionOptions options;
1767   options.has_audio = true;
1768   options.has_video = true;
1769   talk_base::scoped_ptr<SessionDescription> offer, answer;
1770   const cricket::MediaContentDescription* audio_media_desc;
1771   const cricket::MediaContentDescription* video_media_desc;
1772   const cricket::TransportDescription* audio_trans_desc;
1773   const cricket::TransportDescription* video_trans_desc;
1774
1775   // Generate an offer with SDES and DTLS support.
1776   offer.reset(f1_.CreateOffer(options, NULL));
1777   ASSERT_TRUE(offer.get() != NULL);
1778
1779   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1780       offer->GetContentDescriptionByName("audio"));
1781   ASSERT_TRUE(audio_media_desc != NULL);
1782   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1783       offer->GetContentDescriptionByName("video"));
1784   ASSERT_TRUE(video_media_desc != NULL);
1785   EXPECT_EQ(2u, audio_media_desc->cryptos().size());
1786   EXPECT_EQ(1u, video_media_desc->cryptos().size());
1787
1788   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
1789   ASSERT_TRUE(audio_trans_desc != NULL);
1790   video_trans_desc = offer->GetTransportDescriptionByName("video");
1791   ASSERT_TRUE(video_trans_desc != NULL);
1792   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1793   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1794
1795   // Generate an answer with only SDES support, since tdf2 has crypto disabled.
1796   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1797   ASSERT_TRUE(answer.get() != NULL);
1798
1799   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1800       answer->GetContentDescriptionByName("audio"));
1801   ASSERT_TRUE(audio_media_desc != NULL);
1802   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1803       answer->GetContentDescriptionByName("video"));
1804   ASSERT_TRUE(video_media_desc != NULL);
1805   EXPECT_EQ(1u, audio_media_desc->cryptos().size());
1806   EXPECT_EQ(1u, video_media_desc->cryptos().size());
1807
1808   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
1809   ASSERT_TRUE(audio_trans_desc != NULL);
1810   video_trans_desc = answer->GetTransportDescriptionByName("video");
1811   ASSERT_TRUE(video_trans_desc != NULL);
1812   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
1813   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
1814
1815   // Enable DTLS; the answer should now only have DTLS support.
1816   tdf2_.set_secure(SEC_ENABLED);
1817   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1818   ASSERT_TRUE(answer.get() != NULL);
1819
1820   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1821       answer->GetContentDescriptionByName("audio"));
1822   ASSERT_TRUE(audio_media_desc != NULL);
1823   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1824       answer->GetContentDescriptionByName("video"));
1825   ASSERT_TRUE(video_media_desc != NULL);
1826   EXPECT_TRUE(audio_media_desc->cryptos().empty());
1827   EXPECT_TRUE(video_media_desc->cryptos().empty());
1828   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
1829             audio_media_desc->protocol());
1830   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
1831             video_media_desc->protocol());
1832
1833   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
1834   ASSERT_TRUE(audio_trans_desc != NULL);
1835   video_trans_desc = answer->GetTransportDescriptionByName("video");
1836   ASSERT_TRUE(video_trans_desc != NULL);
1837   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1838   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1839
1840   // Try creating offer again. DTLS enabled now, crypto's should be empty
1841   // in new offer.
1842   offer.reset(f1_.CreateOffer(options, offer.get()));
1843   ASSERT_TRUE(offer.get() != NULL);
1844   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1845       offer->GetContentDescriptionByName("audio"));
1846   ASSERT_TRUE(audio_media_desc != NULL);
1847   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1848       offer->GetContentDescriptionByName("video"));
1849   ASSERT_TRUE(video_media_desc != NULL);
1850   EXPECT_TRUE(audio_media_desc->cryptos().empty());
1851   EXPECT_TRUE(video_media_desc->cryptos().empty());
1852
1853   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
1854   ASSERT_TRUE(audio_trans_desc != NULL);
1855   video_trans_desc = offer->GetTransportDescriptionByName("video");
1856   ASSERT_TRUE(video_trans_desc != NULL);
1857   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1858   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1859 }
1860
1861 // Test that an answer can't be created if cryptos are required but the offer is
1862 // unsecure.
1863 TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
1864   MediaSessionOptions options;
1865   f1_.set_secure(SEC_DISABLED);
1866   tdf1_.set_secure(SEC_DISABLED);
1867   f2_.set_secure(SEC_REQUIRED);
1868   tdf1_.set_secure(SEC_ENABLED);
1869
1870   talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
1871                                                                   NULL));
1872   ASSERT_TRUE(offer.get() != NULL);
1873   talk_base::scoped_ptr<SessionDescription> answer(
1874       f2_.CreateAnswer(offer.get(), options, NULL));
1875   EXPECT_TRUE(answer.get() == NULL);
1876 }
1877
1878 // Test that we accept a DTLS offer without SDES and create an appropriate
1879 // answer.
1880 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
1881   f1_.set_secure(SEC_DISABLED);
1882   f2_.set_secure(SEC_ENABLED);
1883   tdf1_.set_secure(SEC_ENABLED);
1884   tdf2_.set_secure(SEC_ENABLED);
1885   MediaSessionOptions options;
1886   options.has_audio = true;
1887   options.has_video = true;
1888   options.data_channel_type = cricket::DCT_RTP;
1889
1890   talk_base::scoped_ptr<SessionDescription> offer, answer;
1891
1892   // Generate an offer with DTLS but without SDES.
1893   offer.reset(f1_.CreateOffer(options, NULL));
1894   ASSERT_TRUE(offer.get() != NULL);
1895
1896   const AudioContentDescription* audio_offer =
1897       GetFirstAudioContentDescription(offer.get());
1898   ASSERT_TRUE(audio_offer->cryptos().empty());
1899   const VideoContentDescription* video_offer =
1900       GetFirstVideoContentDescription(offer.get());
1901   ASSERT_TRUE(video_offer->cryptos().empty());
1902   const DataContentDescription* data_offer =
1903       GetFirstDataContentDescription(offer.get());
1904   ASSERT_TRUE(data_offer->cryptos().empty());
1905
1906   const cricket::TransportDescription* audio_offer_trans_desc =
1907       offer->GetTransportDescriptionByName("audio");
1908   ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
1909   const cricket::TransportDescription* video_offer_trans_desc =
1910       offer->GetTransportDescriptionByName("video");
1911   ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
1912   const cricket::TransportDescription* data_offer_trans_desc =
1913       offer->GetTransportDescriptionByName("data");
1914   ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
1915
1916   // Generate an answer with DTLS.
1917   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1918   ASSERT_TRUE(answer.get() != NULL);
1919
1920   const cricket::TransportDescription* audio_answer_trans_desc =
1921       answer->GetTransportDescriptionByName("audio");
1922   EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
1923   const cricket::TransportDescription* video_answer_trans_desc =
1924       answer->GetTransportDescriptionByName("video");
1925   EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
1926   const cricket::TransportDescription* data_answer_trans_desc =
1927       answer->GetTransportDescriptionByName("data");
1928   EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
1929 }
1930
1931 // Verifies if vad_enabled option is set to false, CN codecs are not present in
1932 // offer or answer.
1933 TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
1934   MediaSessionOptions options;
1935   options.has_audio = true;
1936   options.has_video = true;
1937   talk_base::scoped_ptr<SessionDescription> offer(
1938       f1_.CreateOffer(options, NULL));
1939   ASSERT_TRUE(offer.get() != NULL);
1940   const ContentInfo* audio_content = offer->GetContentByName("audio");
1941   EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
1942
1943   options.vad_enabled = false;
1944   offer.reset(f1_.CreateOffer(options, NULL));
1945   ASSERT_TRUE(offer.get() != NULL);
1946   audio_content = offer->GetContentByName("audio");
1947   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
1948   talk_base::scoped_ptr<SessionDescription> answer(
1949       f1_.CreateAnswer(offer.get(), options, NULL));
1950   ASSERT_TRUE(answer.get() != NULL);
1951   audio_content = answer->GetContentByName("audio");
1952   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
1953 }