Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / app / webrtc / webrtcsession_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2012, 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 "talk/app/webrtc/audiotrack.h"
29 #include "talk/app/webrtc/jsepicecandidate.h"
30 #include "talk/app/webrtc/jsepsessiondescription.h"
31 #include "talk/app/webrtc/mediastreamsignaling.h"
32 #include "talk/app/webrtc/streamcollection.h"
33 #include "talk/app/webrtc/videotrack.h"
34 #include "talk/app/webrtc/test/fakeconstraints.h"
35 #include "talk/app/webrtc/test/fakedtlsidentityservice.h"
36 #include "talk/app/webrtc/test/fakemediastreamsignaling.h"
37 #include "talk/app/webrtc/webrtcsession.h"
38 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
39 #include "talk/base/fakenetwork.h"
40 #include "talk/base/firewallsocketserver.h"
41 #include "talk/base/gunit.h"
42 #include "talk/base/logging.h"
43 #include "talk/base/network.h"
44 #include "talk/base/physicalsocketserver.h"
45 #include "talk/base/ssladapter.h"
46 #include "talk/base/sslstreamadapter.h"
47 #include "talk/base/stringutils.h"
48 #include "talk/base/thread.h"
49 #include "talk/base/virtualsocketserver.h"
50 #include "talk/media/base/fakemediaengine.h"
51 #include "talk/media/base/fakevideorenderer.h"
52 #include "talk/media/base/mediachannel.h"
53 #include "talk/media/devices/fakedevicemanager.h"
54 #include "talk/p2p/base/stunserver.h"
55 #include "talk/p2p/base/teststunserver.h"
56 #include "talk/p2p/client/basicportallocator.h"
57 #include "talk/session/media/channelmanager.h"
58 #include "talk/session/media/mediasession.h"
59
60 #define MAYBE_SKIP_TEST(feature)                    \
61   if (!(feature())) {                               \
62     LOG(LS_INFO) << "Feature disabled... skipping"; \
63     return;                                         \
64   }
65
66 using cricket::BaseSession;
67 using cricket::DF_PLAY;
68 using cricket::DF_SEND;
69 using cricket::FakeVoiceMediaChannel;
70 using cricket::NS_GINGLE_P2P;
71 using cricket::NS_JINGLE_ICE_UDP;
72 using cricket::TransportInfo;
73 using talk_base::SocketAddress;
74 using talk_base::scoped_ptr;
75 using webrtc::CreateSessionDescription;
76 using webrtc::CreateSessionDescriptionObserver;
77 using webrtc::CreateSessionDescriptionRequest;
78 using webrtc::DTLSIdentityRequestObserver;
79 using webrtc::DTLSIdentityServiceInterface;
80 using webrtc::FakeConstraints;
81 using webrtc::IceCandidateCollection;
82 using webrtc::JsepIceCandidate;
83 using webrtc::JsepSessionDescription;
84 using webrtc::PeerConnectionFactoryInterface;
85 using webrtc::PeerConnectionInterface;
86 using webrtc::SessionDescriptionInterface;
87 using webrtc::StreamCollection;
88 using webrtc::WebRtcSession;
89 using webrtc::kBundleWithoutRtcpMux;
90 using webrtc::kCreateChannelFailed;
91 using webrtc::kInvalidSdp;
92 using webrtc::kMlineMismatch;
93 using webrtc::kPushDownTDFailed;
94 using webrtc::kSdpWithoutCrypto;
95 using webrtc::kSdpWithoutIceUfragPwd;
96 using webrtc::kSdpWithoutSdesAndDtlsDisabled;
97 using webrtc::kSessionError;
98 using webrtc::kSessionErrorDesc;
99
100 static const int kClientAddrPort = 0;
101 static const char kClientAddrHost1[] = "11.11.11.11";
102 static const char kClientAddrHost2[] = "22.22.22.22";
103 static const char kStunAddrHost[] = "99.99.99.1";
104
105 static const char kSessionVersion[] = "1";
106
107 // Media index of candidates belonging to the first media content.
108 static const int kMediaContentIndex0 = 0;
109 static const char kMediaContentName0[] = "audio";
110
111 // Media index of candidates belonging to the second media content.
112 static const int kMediaContentIndex1 = 1;
113 static const char kMediaContentName1[] = "video";
114
115 static const int kIceCandidatesTimeout = 10000;
116
117 static const char kFakeDtlsFingerprint[] =
118     "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
119     "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
120
121 // Add some extra |newlines| to the |message| after |line|.
122 static void InjectAfter(const std::string& line,
123                         const std::string& newlines,
124                         std::string* message) {
125   const std::string tmp = line + newlines;
126   talk_base::replace_substrs(line.c_str(), line.length(),
127                              tmp.c_str(), tmp.length(), message);
128 }
129
130 class MockIceObserver : public webrtc::IceObserver {
131  public:
132   MockIceObserver()
133       : oncandidatesready_(false),
134         ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
135         ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
136   }
137
138   virtual void OnIceConnectionChange(
139       PeerConnectionInterface::IceConnectionState new_state) {
140     ice_connection_state_ = new_state;
141   }
142   virtual void OnIceGatheringChange(
143       PeerConnectionInterface::IceGatheringState new_state) {
144     // We can never transition back to "new".
145     EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
146     ice_gathering_state_ = new_state;
147
148     // oncandidatesready_ really means "ICE gathering is complete".
149     // This if statement ensures that this value remains correct when we
150     // transition from kIceGatheringComplete to kIceGatheringGathering.
151     if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
152       oncandidatesready_ = false;
153     }
154   }
155
156   // Found a new candidate.
157   virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
158     switch (candidate->sdp_mline_index()) {
159       case kMediaContentIndex0:
160         mline_0_candidates_.push_back(candidate->candidate());
161         break;
162       case kMediaContentIndex1:
163         mline_1_candidates_.push_back(candidate->candidate());
164         break;
165       default:
166         ASSERT(false);
167     }
168
169     // The ICE gathering state should always be Gathering when a candidate is
170     // received (or possibly Completed in the case of the final candidate).
171     EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
172   }
173
174   // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
175   virtual void OnIceComplete() {
176     EXPECT_FALSE(oncandidatesready_);
177     oncandidatesready_ = true;
178
179     // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
180     // be called approximately simultaneously.  For ease of testing, this
181     // check additionally requires that they be called in the above order.
182     EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
183               ice_gathering_state_);
184   }
185
186   bool oncandidatesready_;
187   std::vector<cricket::Candidate> mline_0_candidates_;
188   std::vector<cricket::Candidate> mline_1_candidates_;
189   PeerConnectionInterface::IceConnectionState ice_connection_state_;
190   PeerConnectionInterface::IceGatheringState ice_gathering_state_;
191 };
192
193 class WebRtcSessionForTest : public webrtc::WebRtcSession {
194  public:
195   WebRtcSessionForTest(cricket::ChannelManager* cmgr,
196                        talk_base::Thread* signaling_thread,
197                        talk_base::Thread* worker_thread,
198                        cricket::PortAllocator* port_allocator,
199                        webrtc::IceObserver* ice_observer,
200                        webrtc::MediaStreamSignaling* mediastream_signaling)
201     : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
202                     mediastream_signaling) {
203     RegisterIceObserver(ice_observer);
204   }
205   virtual ~WebRtcSessionForTest() {}
206
207   using cricket::BaseSession::GetTransportProxy;
208   using webrtc::WebRtcSession::SetAudioPlayout;
209   using webrtc::WebRtcSession::SetAudioSend;
210   using webrtc::WebRtcSession::SetCaptureDevice;
211   using webrtc::WebRtcSession::SetVideoPlayout;
212   using webrtc::WebRtcSession::SetVideoSend;
213 };
214
215 class WebRtcSessionCreateSDPObserverForTest
216     : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
217  public:
218   enum State {
219     kInit,
220     kFailed,
221     kSucceeded,
222   };
223   WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
224
225   // CreateSessionDescriptionObserver implementation.
226   virtual void OnSuccess(SessionDescriptionInterface* desc) {
227     description_.reset(desc);
228     state_ = kSucceeded;
229   }
230   virtual void OnFailure(const std::string& error) {
231     state_ = kFailed;
232   }
233
234   SessionDescriptionInterface* description() { return description_.get(); }
235
236   SessionDescriptionInterface* ReleaseDescription() {
237     return description_.release();
238   }
239
240   State state() const { return state_; }
241
242  protected:
243   ~WebRtcSessionCreateSDPObserverForTest() {}
244
245  private:
246   talk_base::scoped_ptr<SessionDescriptionInterface> description_;
247   State state_;
248 };
249
250 class FakeAudioRenderer : public cricket::AudioRenderer {
251  public:
252   FakeAudioRenderer() : channel_id_(-1) {}
253
254   virtual void AddChannel(int channel_id) OVERRIDE {
255     ASSERT(channel_id_ == -1);
256     channel_id_ = channel_id;
257   }
258   virtual void RemoveChannel(int channel_id) OVERRIDE {
259     ASSERT(channel_id == channel_id_);
260     channel_id_ = -1;
261   }
262
263   int channel_id() const { return channel_id_; }
264  private:
265   int channel_id_;
266 };
267
268 class WebRtcSessionTest : public testing::Test {
269  protected:
270   // TODO Investigate why ChannelManager crashes, if it's created
271   // after stun_server.
272   WebRtcSessionTest()
273     : media_engine_(new cricket::FakeMediaEngine()),
274       data_engine_(new cricket::FakeDataEngine()),
275       device_manager_(new cricket::FakeDeviceManager()),
276       channel_manager_(new cricket::ChannelManager(
277          media_engine_, data_engine_, device_manager_,
278          new cricket::CaptureManager(), talk_base::Thread::Current())),
279       tdesc_factory_(new cricket::TransportDescriptionFactory()),
280       desc_factory_(new cricket::MediaSessionDescriptionFactory(
281           channel_manager_.get(), tdesc_factory_.get())),
282       pss_(new talk_base::PhysicalSocketServer),
283       vss_(new talk_base::VirtualSocketServer(pss_.get())),
284       fss_(new talk_base::FirewallSocketServer(vss_.get())),
285       ss_scope_(fss_.get()),
286       stun_socket_addr_(talk_base::SocketAddress(kStunAddrHost,
287                                                  cricket::STUN_SERVER_PORT)),
288       stun_server_(talk_base::Thread::Current(), stun_socket_addr_),
289       allocator_(&network_manager_, stun_socket_addr_,
290                  SocketAddress(), SocketAddress(), SocketAddress()),
291       mediastream_signaling_(channel_manager_.get()) {
292     tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
293     allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
294                          cricket::PORTALLOCATOR_DISABLE_RELAY |
295                          cricket::PORTALLOCATOR_ENABLE_BUNDLE);
296     EXPECT_TRUE(channel_manager_->Init());
297     desc_factory_->set_add_legacy_streams(false);
298   }
299
300   static void SetUpTestCase() {
301     talk_base::InitializeSSL();
302   }
303
304   static void TearDownTestCase() {
305     talk_base::CleanupSSL();
306   }
307
308   void AddInterface(const SocketAddress& addr) {
309     network_manager_.AddInterface(addr);
310   }
311
312   void Init(DTLSIdentityServiceInterface* identity_service) {
313     ASSERT_TRUE(session_.get() == NULL);
314     session_.reset(new WebRtcSessionForTest(
315         channel_manager_.get(), talk_base::Thread::Current(),
316         talk_base::Thread::Current(), &allocator_,
317         &observer_,
318         &mediastream_signaling_));
319
320     EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
321         observer_.ice_connection_state_);
322     EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
323         observer_.ice_gathering_state_);
324
325     EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
326                                      identity_service));
327   }
328
329   void InitWithDtmfCodec() {
330     // Add kTelephoneEventCodec for dtmf test.
331     const cricket::AudioCodec kTelephoneEventCodec(
332         106, "telephone-event", 8000, 0, 1, 0);
333     std::vector<cricket::AudioCodec> codecs;
334     codecs.push_back(kTelephoneEventCodec);
335     media_engine_->SetAudioCodecs(codecs);
336     desc_factory_->set_audio_codecs(codecs);
337     Init(NULL);
338   }
339
340   void InitWithDtls(bool identity_request_should_fail = false) {
341     FakeIdentityService* identity_service = new FakeIdentityService();
342     identity_service->set_should_fail(identity_request_should_fail);
343     Init(identity_service);
344   }
345
346   // Creates a local offer and applies it. Starts ice.
347   // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
348   // to decide which streams to create.
349   void InitiateCall() {
350     SessionDescriptionInterface* offer = CreateOffer(NULL);
351     SetLocalDescriptionWithoutError(offer);
352     EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
353         observer_.ice_gathering_state_,
354         kIceCandidatesTimeout);
355   }
356
357   SessionDescriptionInterface* CreateOffer(
358       const webrtc::MediaConstraintsInterface* constraints) {
359     talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
360         observer = new WebRtcSessionCreateSDPObserverForTest();
361     session_->CreateOffer(observer, constraints);
362     EXPECT_TRUE_WAIT(
363         observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
364         2000);
365     return observer->ReleaseDescription();
366   }
367
368   SessionDescriptionInterface* CreateAnswer(
369       const webrtc::MediaConstraintsInterface* constraints) {
370     talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
371         = new WebRtcSessionCreateSDPObserverForTest();
372     session_->CreateAnswer(observer, constraints);
373     EXPECT_TRUE_WAIT(
374         observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
375         2000);
376     return observer->ReleaseDescription();
377   }
378
379   bool ChannelsExist() const {
380     return (session_->voice_channel() != NULL &&
381             session_->video_channel() != NULL);
382   }
383
384   void CheckTransportChannels() const {
385     EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
386     EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
387     EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
388     EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
389   }
390
391   void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
392     ASSERT_TRUE(session_.get() != NULL);
393     const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
394     ASSERT_TRUE(content != NULL);
395     const cricket::AudioContentDescription* audio_content =
396         static_cast<const cricket::AudioContentDescription*>(
397             content->description);
398     ASSERT_TRUE(audio_content != NULL);
399     ASSERT_EQ(1U, audio_content->cryptos().size());
400     ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
401     ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
402               audio_content->cryptos()[0].cipher_suite);
403     EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
404               audio_content->protocol());
405
406     content = cricket::GetFirstVideoContent(sdp);
407     ASSERT_TRUE(content != NULL);
408     const cricket::VideoContentDescription* video_content =
409         static_cast<const cricket::VideoContentDescription*>(
410             content->description);
411     ASSERT_TRUE(video_content != NULL);
412     ASSERT_EQ(1U, video_content->cryptos().size());
413     ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
414               video_content->cryptos()[0].cipher_suite);
415     ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
416     EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
417               video_content->protocol());
418   }
419
420   void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
421     const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
422     ASSERT_TRUE(content != NULL);
423     const cricket::AudioContentDescription* audio_content =
424         static_cast<const cricket::AudioContentDescription*>(
425             content->description);
426     ASSERT_TRUE(audio_content != NULL);
427     ASSERT_EQ(0U, audio_content->cryptos().size());
428
429     content = cricket::GetFirstVideoContent(sdp);
430     ASSERT_TRUE(content != NULL);
431     const cricket::VideoContentDescription* video_content =
432         static_cast<const cricket::VideoContentDescription*>(
433             content->description);
434     ASSERT_TRUE(video_content != NULL);
435     ASSERT_EQ(0U, video_content->cryptos().size());
436
437     if (dtls) {
438       EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
439                 audio_content->protocol());
440       EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
441                 video_content->protocol());
442     } else {
443       EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
444                 audio_content->protocol());
445       EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
446                 video_content->protocol());
447     }
448   }
449
450   // Set the internal fake description factories to do DTLS-SRTP.
451   void SetFactoryDtlsSrtp() {
452     desc_factory_->set_secure(cricket::SEC_ENABLED);
453     std::string identity_name = "WebRTC" +
454         talk_base::ToString(talk_base::CreateRandomId());
455     identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
456     tdesc_factory_->set_identity(identity_.get());
457     tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
458   }
459
460   void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
461                                bool expected) {
462     const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
463     ASSERT_TRUE(audio != NULL);
464     ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
465     const TransportInfo* video = sdp->GetTransportInfoByName("video");
466     ASSERT_TRUE(video != NULL);
467     ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
468   }
469
470   void VerifyAnswerFromNonCryptoOffer() {
471     // Create a SDP without Crypto.
472     cricket::MediaSessionOptions options;
473     options.has_video = true;
474     JsepSessionDescription* offer(
475         CreateRemoteOffer(options, cricket::SEC_DISABLED));
476     ASSERT_TRUE(offer != NULL);
477     VerifyNoCryptoParams(offer->description(), false);
478     SetRemoteDescriptionOfferExpectError(
479         "Called with a SDP without crypto enabled", offer);
480     const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
481     // Answer should be NULL as no crypto params in offer.
482     ASSERT_TRUE(answer == NULL);
483   }
484
485   void VerifyAnswerFromCryptoOffer() {
486     cricket::MediaSessionOptions options;
487     options.has_video = true;
488     options.bundle_enabled = true;
489     scoped_ptr<JsepSessionDescription> offer(
490         CreateRemoteOffer(options, cricket::SEC_REQUIRED));
491     ASSERT_TRUE(offer.get() != NULL);
492     VerifyCryptoParams(offer->description());
493     SetRemoteDescriptionWithoutError(offer.release());
494     scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
495     ASSERT_TRUE(answer.get() != NULL);
496     VerifyCryptoParams(answer->description());
497   }
498
499   void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
500                                   const cricket::SessionDescription* desc2,
501                                   bool expect_equal) {
502     if (desc1->contents().size() != desc2->contents().size()) {
503       EXPECT_FALSE(expect_equal);
504       return;
505     }
506
507     const cricket::ContentInfos& contents = desc1->contents();
508     cricket::ContentInfos::const_iterator it = contents.begin();
509
510     for (; it != contents.end(); ++it) {
511       const cricket::TransportDescription* transport_desc1 =
512           desc1->GetTransportDescriptionByName(it->name);
513       const cricket::TransportDescription* transport_desc2 =
514           desc2->GetTransportDescriptionByName(it->name);
515       if (!transport_desc1 || !transport_desc2) {
516         EXPECT_FALSE(expect_equal);
517         return;
518       }
519       if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
520           transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
521         EXPECT_FALSE(expect_equal);
522         return;
523       }
524     }
525     EXPECT_TRUE(expect_equal);
526   }
527
528   void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
529                               std::string *sdp) {
530     const cricket::SessionDescription* desc = current_desc->description();
531     EXPECT_TRUE(current_desc->ToString(sdp));
532
533     const cricket::ContentInfos& contents = desc->contents();
534     cricket::ContentInfos::const_iterator it = contents.begin();
535     // Replace ufrag and pwd lines with empty strings.
536     for (; it != contents.end(); ++it) {
537       const cricket::TransportDescription* transport_desc =
538           desc->GetTransportDescriptionByName(it->name);
539       std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
540           + "\r\n";
541       std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
542           + "\r\n";
543       talk_base::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
544                                  "", 0,
545                                  sdp);
546       talk_base::replace_substrs(pwd_line.c_str(), pwd_line.length(),
547                                  "", 0,
548                                  sdp);
549     }
550   }
551
552   // Creates a remote offer and and applies it as a remote description,
553   // creates a local answer and applies is as a local description.
554   // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
555   // to decide which local and remote streams to create.
556   void CreateAndSetRemoteOfferAndLocalAnswer() {
557     SessionDescriptionInterface* offer = CreateRemoteOffer();
558     SetRemoteDescriptionWithoutError(offer);
559     SessionDescriptionInterface* answer = CreateAnswer(NULL);
560     SetLocalDescriptionWithoutError(answer);
561   }
562   void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
563     EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
564   }
565   void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
566                                       BaseSession::State expected_state) {
567     SetLocalDescriptionWithoutError(desc);
568     EXPECT_EQ(expected_state, session_->state());
569   }
570   void SetLocalDescriptionExpectError(const std::string& action,
571                                       const std::string& expected_error,
572                                       SessionDescriptionInterface* desc) {
573     std::string error;
574     EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
575     std::string sdp_type = "local ";
576     sdp_type.append(action);
577     EXPECT_NE(std::string::npos, error.find(sdp_type));
578     EXPECT_NE(std::string::npos, error.find(expected_error));
579   }
580   void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
581                                            SessionDescriptionInterface* desc) {
582     SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
583                                    expected_error, desc);
584   }
585   void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
586                                             SessionDescriptionInterface* desc) {
587     SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
588                                    expected_error, desc);
589   }
590   void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
591     EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
592   }
593   void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
594                                        BaseSession::State expected_state) {
595     SetRemoteDescriptionWithoutError(desc);
596     EXPECT_EQ(expected_state, session_->state());
597   }
598   void SetRemoteDescriptionExpectError(const std::string& action,
599                                        const std::string& expected_error,
600                                        SessionDescriptionInterface* desc) {
601     std::string error;
602     EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
603     std::string sdp_type = "remote ";
604     sdp_type.append(action);
605     EXPECT_NE(std::string::npos, error.find(sdp_type));
606     EXPECT_NE(std::string::npos, error.find(expected_error));
607   }
608   void SetRemoteDescriptionOfferExpectError(
609       const std::string& expected_error, SessionDescriptionInterface* desc) {
610     SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
611                                     expected_error, desc);
612   }
613   void SetRemoteDescriptionPranswerExpectError(
614       const std::string& expected_error, SessionDescriptionInterface* desc) {
615     SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
616                                     expected_error, desc);
617   }
618   void SetRemoteDescriptionAnswerExpectError(
619       const std::string& expected_error, SessionDescriptionInterface* desc) {
620     SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
621                                     expected_error, desc);
622   }
623
624   void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
625       SessionDescriptionInterface** nocrypto_answer) {
626     // Create a SDP without Crypto.
627     cricket::MediaSessionOptions options;
628     options.has_video = true;
629     options.bundle_enabled = true;
630     *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
631     ASSERT_TRUE(*offer != NULL);
632     VerifyCryptoParams((*offer)->description());
633
634     *nocrypto_answer = CreateRemoteAnswer(*offer, options,
635                                           cricket::SEC_DISABLED);
636     EXPECT_TRUE(*nocrypto_answer != NULL);
637   }
638
639   JsepSessionDescription* CreateRemoteOfferWithVersion(
640         cricket::MediaSessionOptions options,
641         cricket::SecurePolicy secure_policy,
642         const std::string& session_version,
643         const SessionDescriptionInterface* current_desc) {
644     std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
645     const cricket::SessionDescription* cricket_desc = NULL;
646     if (current_desc) {
647       cricket_desc = current_desc->description();
648       session_id = current_desc->session_id();
649     }
650
651     desc_factory_->set_secure(secure_policy);
652     JsepSessionDescription* offer(
653         new JsepSessionDescription(JsepSessionDescription::kOffer));
654     if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
655                            session_id, session_version)) {
656       delete offer;
657       offer = NULL;
658     }
659     return offer;
660   }
661   JsepSessionDescription* CreateRemoteOffer(
662       cricket::MediaSessionOptions options) {
663     return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
664                                         kSessionVersion, NULL);
665   }
666   JsepSessionDescription* CreateRemoteOffer(
667       cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
668     return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
669   }
670   JsepSessionDescription* CreateRemoteOffer(
671       cricket::MediaSessionOptions options,
672       const SessionDescriptionInterface* current_desc) {
673     return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
674                                         kSessionVersion, current_desc);
675   }
676
677   JsepSessionDescription* CreateRemoteOfferWithSctpPort(
678       const char* sctp_stream_name, int new_port,
679       cricket::MediaSessionOptions options) {
680     options.data_channel_type = cricket::DCT_SCTP;
681     options.AddStream(cricket::MEDIA_TYPE_DATA, "datachannel",
682                       sctp_stream_name);
683     return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
684   }
685
686   // Takes ownership of offer_basis (and deletes it).
687   JsepSessionDescription* ChangeSDPSctpPort(
688       int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
689     // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
690     // SessionDescription from the mutated string.
691     const char* default_port_str = "5000";
692     char new_port_str[16];
693     talk_base::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
694     std::string offer_str;
695     offer_basis->ToString(&offer_str);
696     talk_base::replace_substrs(default_port_str, strlen(default_port_str),
697                                new_port_str, strlen(new_port_str),
698                                &offer_str);
699     JsepSessionDescription* offer = new JsepSessionDescription(
700         offer_basis->type());
701     delete offer_basis;
702     offer->Initialize(offer_str, NULL);
703     return offer;
704   }
705
706   // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
707   // before this function to decide which streams to create.
708   JsepSessionDescription* CreateRemoteOffer() {
709     cricket::MediaSessionOptions options;
710     mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
711     return CreateRemoteOffer(options, session_->remote_description());
712   }
713
714   JsepSessionDescription* CreateRemoteAnswer(
715       const SessionDescriptionInterface* offer,
716       cricket::MediaSessionOptions options,
717       cricket::SecurePolicy policy) {
718     desc_factory_->set_secure(policy);
719     const std::string session_id =
720         talk_base::ToString(talk_base::CreateRandomId64());
721     JsepSessionDescription* answer(
722         new JsepSessionDescription(JsepSessionDescription::kAnswer));
723     if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
724                                                         options, NULL),
725                             session_id, kSessionVersion)) {
726       delete answer;
727       answer = NULL;
728     }
729     return answer;
730   }
731
732   JsepSessionDescription* CreateRemoteAnswer(
733       const SessionDescriptionInterface* offer,
734       cricket::MediaSessionOptions options) {
735       return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
736   }
737
738   // Creates an answer session description with streams based on
739   // |mediastream_signaling_|. Call
740   // mediastream_signaling_.UseOptionsWithStreamX() before this function
741   // to decide which streams to create.
742   JsepSessionDescription* CreateRemoteAnswer(
743       const SessionDescriptionInterface* offer) {
744     cricket::MediaSessionOptions options;
745     mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
746     return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
747   }
748
749   void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
750     AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
751     Init(NULL);
752     mediastream_signaling_.SendAudioVideoStream1();
753     FakeConstraints constraints;
754     constraints.SetMandatoryUseRtpMux(bundle);
755     SessionDescriptionInterface* offer = CreateOffer(&constraints);
756     // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
757     // and answer.
758     SetLocalDescriptionWithoutError(offer);
759
760     talk_base::scoped_ptr<SessionDescriptionInterface> answer(
761         CreateRemoteAnswer(session_->local_description()));
762     std::string sdp;
763     EXPECT_TRUE(answer->ToString(&sdp));
764
765     size_t expected_candidate_num = 2;
766     if (!rtcp_mux) {
767       // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
768       // for rtp and rtcp.
769       expected_candidate_num = 4;
770       // Disable rtcp-mux from the answer
771       const std::string kRtcpMux = "a=rtcp-mux";
772       const std::string kXRtcpMux = "a=xrtcp-mux";
773       talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
774                                  kXRtcpMux.c_str(), kXRtcpMux.length(),
775                                  &sdp);
776     }
777
778     SessionDescriptionInterface* new_answer = CreateSessionDescription(
779         JsepSessionDescription::kAnswer, sdp, NULL);
780
781     // SetRemoteDescription to enable rtcp mux.
782     SetRemoteDescriptionWithoutError(new_answer);
783     EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
784     EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
785     EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
786     for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
787       cricket::Candidate c0 = observer_.mline_0_candidates_[i];
788       cricket::Candidate c1 = observer_.mline_1_candidates_[i];
789       if (bundle) {
790         EXPECT_TRUE(c0.IsEquivalent(c1));
791       } else {
792         EXPECT_FALSE(c0.IsEquivalent(c1));
793       }
794     }
795   }
796   // Tests that we can only send DTMF when the dtmf codec is supported.
797   void TestCanInsertDtmf(bool can) {
798     if (can) {
799       InitWithDtmfCodec();
800     } else {
801       Init(NULL);
802     }
803     mediastream_signaling_.SendAudioVideoStream1();
804     CreateAndSetRemoteOfferAndLocalAnswer();
805     EXPECT_FALSE(session_->CanInsertDtmf(""));
806     EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
807   }
808
809   // The method sets up a call from the session to itself, in a loopback
810   // arrangement.  It also uses a firewall rule to create a temporary
811   // disconnection, and then a permanent disconnection.
812   // This code is placed in a method so that it can be invoked
813   // by multiple tests with different allocators (e.g. with and without BUNDLE).
814   // While running the call, this method also checks if the session goes through
815   // the correct sequence of ICE states when a connection is established,
816   // broken, and re-established.
817   // The Connection state should go:
818   // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
819   //     -> Failed.
820   // The Gathering state should go: New -> Gathering -> Completed.
821   void TestLoopbackCall() {
822     AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
823     Init(NULL);
824     mediastream_signaling_.SendAudioVideoStream1();
825     SessionDescriptionInterface* offer = CreateOffer(NULL);
826
827     EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
828               observer_.ice_gathering_state_);
829     SetLocalDescriptionWithoutError(offer);
830     EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
831               observer_.ice_connection_state_);
832     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
833                    observer_.ice_gathering_state_,
834                    kIceCandidatesTimeout);
835     EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
836     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
837                    observer_.ice_gathering_state_,
838                    kIceCandidatesTimeout);
839
840     std::string sdp;
841     offer->ToString(&sdp);
842     SessionDescriptionInterface* desc =
843         webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
844     ASSERT_TRUE(desc != NULL);
845     SetRemoteDescriptionWithoutError(desc);
846
847     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
848                    observer_.ice_connection_state_,
849                    kIceCandidatesTimeout);
850     // The ice connection state is "Connected" too briefly to catch in a test.
851     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
852                    observer_.ice_connection_state_,
853                    kIceCandidatesTimeout);
854
855     // Adding firewall rule to block ping requests, which should cause
856     // transport channel failure.
857     fss_->AddRule(false,
858                   talk_base::FP_ANY,
859                   talk_base::FD_ANY,
860                   talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
861     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
862                    observer_.ice_connection_state_,
863                    kIceCandidatesTimeout);
864
865     // Clearing the rules, session should move back to completed state.
866     fss_->ClearRules();
867     // Session is automatically calling OnSignalingReady after creation of
868     // new portallocator session which will allocate new set of candidates.
869
870     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
871                    observer_.ice_connection_state_,
872                    kIceCandidatesTimeout);
873
874     // Now we block ping requests and wait until the ICE connection transitions
875     // to the Failed state.  This will take at least 30 seconds because it must
876     // wait for the Port to timeout.
877     int port_timeout = 30000;
878     fss_->AddRule(false,
879                   talk_base::FP_ANY,
880                   talk_base::FD_ANY,
881                   talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
882     EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed,
883                    observer_.ice_connection_state_,
884                    kIceCandidatesTimeout + port_timeout);
885   }
886
887   void VerifyTransportType(const std::string& content_name,
888                            cricket::TransportProtocol protocol) {
889     const cricket::Transport* transport = session_->GetTransport(content_name);
890     ASSERT_TRUE(transport != NULL);
891     EXPECT_EQ(protocol, transport->protocol());
892   }
893
894   // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
895   void AddCNCodecs() {
896     const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
897     const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
898
899     // Add kCNCodec for dtmf test.
900     std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
901     codecs.push_back(kCNCodec1);
902     codecs.push_back(kCNCodec2);
903     media_engine_->SetAudioCodecs(codecs);
904     desc_factory_->set_audio_codecs(codecs);
905   }
906
907   bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
908     const cricket::ContentDescription* description = content->description;
909     ASSERT(description != NULL);
910     const cricket::AudioContentDescription* audio_content_desc =
911         static_cast<const cricket::AudioContentDescription*>(description);
912     ASSERT(audio_content_desc != NULL);
913     for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
914       if (audio_content_desc->codecs()[i].name == "CN")
915         return false;
916     }
917     return true;
918   }
919
920   void SetLocalDescriptionWithDataChannel() {
921     webrtc::InternalDataChannelInit dci;
922     dci.reliable = false;
923     session_->CreateDataChannel("datachannel", &dci);
924     SessionDescriptionInterface* offer = CreateOffer(NULL);
925     SetLocalDescriptionWithoutError(offer);
926   }
927
928   void VerifyMultipleAsyncCreateDescription(
929       bool success, CreateSessionDescriptionRequest::Type type) {
930     InitWithDtls(!success);
931
932     if (type == CreateSessionDescriptionRequest::kAnswer) {
933       cricket::MediaSessionOptions options;
934       scoped_ptr<JsepSessionDescription> offer(
935             CreateRemoteOffer(options, cricket::SEC_REQUIRED));
936       ASSERT_TRUE(offer.get() != NULL);
937       SetRemoteDescriptionWithoutError(offer.release());
938     }
939
940     const int kNumber = 3;
941     talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
942         observers[kNumber];
943     for (int i = 0; i < kNumber; ++i) {
944       observers[i] = new WebRtcSessionCreateSDPObserverForTest();
945       if (type == CreateSessionDescriptionRequest::kOffer) {
946         session_->CreateOffer(observers[i], NULL);
947       } else {
948         session_->CreateAnswer(observers[i], NULL);
949       }
950     }
951
952     WebRtcSessionCreateSDPObserverForTest::State expected_state =
953         success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
954                   WebRtcSessionCreateSDPObserverForTest::kFailed;
955
956     for (int i = 0; i < kNumber; ++i) {
957       EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
958       if (success) {
959         EXPECT_TRUE(observers[i]->description() != NULL);
960       } else {
961         EXPECT_TRUE(observers[i]->description() == NULL);
962       }
963     }
964   }
965
966   cricket::FakeMediaEngine* media_engine_;
967   cricket::FakeDataEngine* data_engine_;
968   cricket::FakeDeviceManager* device_manager_;
969   talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
970   talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
971   talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
972   talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
973   talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
974   talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
975   talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
976   talk_base::SocketServerScope ss_scope_;
977   talk_base::SocketAddress stun_socket_addr_;
978   cricket::TestStunServer stun_server_;
979   talk_base::FakeNetworkManager network_manager_;
980   cricket::BasicPortAllocator allocator_;
981   PeerConnectionFactoryInterface::Options options_;
982   talk_base::scoped_ptr<FakeConstraints> constraints_;
983   FakeMediaStreamSignaling mediastream_signaling_;
984   talk_base::scoped_ptr<WebRtcSessionForTest> session_;
985   MockIceObserver observer_;
986   cricket::FakeVideoMediaChannel* video_channel_;
987   cricket::FakeVoiceMediaChannel* voice_channel_;
988 };
989
990 TEST_F(WebRtcSessionTest, TestInitialize) {
991   Init(NULL);
992 }
993
994 TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
995   InitWithDtls();
996 }
997
998 // Verifies that WebRtcSession uses SEC_REQUIRED by default.
999 TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
1000   Init(NULL);
1001   EXPECT_EQ(cricket::SEC_REQUIRED, session_->SecurePolicy());
1002 }
1003
1004 TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1005   TestSessionCandidatesWithBundleRtcpMux(false, false);
1006 }
1007
1008 // Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1009 // with rtcp-mux and/or bundle.
1010 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1011   TestSessionCandidatesWithBundleRtcpMux(false, true);
1012 }
1013
1014 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1015   TestSessionCandidatesWithBundleRtcpMux(true, true);
1016 }
1017
1018 TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
1019   AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1020   AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
1021   Init(NULL);
1022   mediastream_signaling_.SendAudioVideoStream1();
1023   InitiateCall();
1024   EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1025   EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1026   EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1027 }
1028
1029 TEST_F(WebRtcSessionTest, TestStunError) {
1030   AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1031   AddInterface(talk_base::SocketAddress(kClientAddrHost2, kClientAddrPort));
1032   fss_->AddRule(false,
1033                 talk_base::FP_UDP,
1034                 talk_base::FD_ANY,
1035                 talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1036   Init(NULL);
1037   mediastream_signaling_.SendAudioVideoStream1();
1038   InitiateCall();
1039   // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
1040   EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1041   EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1042   EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1043 }
1044
1045 TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
1046   Init(NULL);
1047   SessionDescriptionInterface* offer = NULL;
1048   // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1049   std::string unknown_action;
1050   SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1051   SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1052 }
1053
1054 // Test creating offers and receive answers and make sure the
1055 // media engine creates the expected send and receive streams.
1056 TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
1057   Init(NULL);
1058   mediastream_signaling_.SendAudioVideoStream1();
1059   SessionDescriptionInterface* offer = CreateOffer(NULL);
1060   const std::string session_id_orig = offer->session_id();
1061   const std::string session_version_orig = offer->session_version();
1062   SetLocalDescriptionWithoutError(offer);
1063
1064   mediastream_signaling_.SendAudioVideoStream2();
1065   SessionDescriptionInterface* answer =
1066       CreateRemoteAnswer(session_->local_description());
1067   SetRemoteDescriptionWithoutError(answer);
1068
1069   video_channel_ = media_engine_->GetVideoChannel(0);
1070   voice_channel_ = media_engine_->GetVoiceChannel(0);
1071
1072   ASSERT_EQ(1u, video_channel_->recv_streams().size());
1073   EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1074
1075   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1076   EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1077
1078   ASSERT_EQ(1u, video_channel_->send_streams().size());
1079   EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1080   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1081   EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1082
1083   // Create new offer without send streams.
1084   mediastream_signaling_.SendNothing();
1085   offer = CreateOffer(NULL);
1086
1087   // Verify the session id is the same and the session version is
1088   // increased.
1089   EXPECT_EQ(session_id_orig, offer->session_id());
1090   EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1091             talk_base::FromString<uint64>(offer->session_version()));
1092
1093   SetLocalDescriptionWithoutError(offer);
1094
1095   mediastream_signaling_.SendAudioVideoStream2();
1096   answer = CreateRemoteAnswer(session_->local_description());
1097   SetRemoteDescriptionWithoutError(answer);
1098
1099   EXPECT_EQ(0u, video_channel_->send_streams().size());
1100   EXPECT_EQ(0u, voice_channel_->send_streams().size());
1101
1102   // Make sure the receive streams have not changed.
1103   ASSERT_EQ(1u, video_channel_->recv_streams().size());
1104   EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1105   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1106   EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1107 }
1108
1109 // Test receiving offers and creating answers and make sure the
1110 // media engine creates the expected send and receive streams.
1111 TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
1112   Init(NULL);
1113   mediastream_signaling_.SendAudioVideoStream2();
1114   SessionDescriptionInterface* offer = CreateOffer(NULL);
1115   SetRemoteDescriptionWithoutError(offer);
1116
1117   mediastream_signaling_.SendAudioVideoStream1();
1118   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1119   SetLocalDescriptionWithoutError(answer);
1120
1121   const std::string session_id_orig = answer->session_id();
1122   const std::string session_version_orig = answer->session_version();
1123
1124   video_channel_ = media_engine_->GetVideoChannel(0);
1125   voice_channel_ = media_engine_->GetVoiceChannel(0);
1126
1127   ASSERT_EQ(1u, video_channel_->recv_streams().size());
1128   EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1129
1130   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1131   EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1132
1133   ASSERT_EQ(1u, video_channel_->send_streams().size());
1134   EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1135   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1136   EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1137
1138   mediastream_signaling_.SendAudioVideoStream1And2();
1139   offer = CreateOffer(NULL);
1140   SetRemoteDescriptionWithoutError(offer);
1141
1142   // Answer by turning off all send streams.
1143   mediastream_signaling_.SendNothing();
1144   answer = CreateAnswer(NULL);
1145
1146   // Verify the session id is the same and the session version is
1147   // increased.
1148   EXPECT_EQ(session_id_orig, answer->session_id());
1149   EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1150             talk_base::FromString<uint64>(answer->session_version()));
1151   SetLocalDescriptionWithoutError(answer);
1152
1153   ASSERT_EQ(2u, video_channel_->recv_streams().size());
1154   EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1155   EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1156   ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1157   EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1158   EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1159
1160   // Make sure we have no send streams.
1161   EXPECT_EQ(0u, video_channel_->send_streams().size());
1162   EXPECT_EQ(0u, voice_channel_->send_streams().size());
1163 }
1164
1165 TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
1166   Init(NULL);
1167   media_engine_->set_fail_create_channel(true);
1168
1169   SessionDescriptionInterface* offer = CreateOffer(NULL);
1170   ASSERT_TRUE(offer != NULL);
1171   // SetRemoteDescription and SetLocalDescription will take the ownership of
1172   // the offer.
1173   SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
1174   offer = CreateOffer(NULL);
1175   ASSERT_TRUE(offer != NULL);
1176   SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1177 }
1178
1179 // Test we will return fail when apply an offer that doesn't have
1180 // crypto enabled.
1181 TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
1182   Init(NULL);
1183   cricket::MediaSessionOptions options;
1184   options.has_video = true;
1185   JsepSessionDescription* offer = CreateRemoteOffer(
1186       options, cricket::SEC_DISABLED);
1187   ASSERT_TRUE(offer != NULL);
1188   VerifyNoCryptoParams(offer->description(), false);
1189   // SetRemoteDescription and SetLocalDescription will take the ownership of
1190   // the offer.
1191   SetRemoteDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
1192   offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1193   ASSERT_TRUE(offer != NULL);
1194   SetLocalDescriptionOfferExpectError(kSdpWithoutCrypto, offer);
1195 }
1196
1197 // Test we will return fail when apply an answer that doesn't have
1198 // crypto enabled.
1199 TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
1200   Init(NULL);
1201   SessionDescriptionInterface* offer = NULL;
1202   SessionDescriptionInterface* answer = NULL;
1203   CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1204   // SetRemoteDescription and SetLocalDescription will take the ownership of
1205   // the offer.
1206   SetRemoteDescriptionWithoutError(offer);
1207   SetLocalDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
1208 }
1209
1210 // Test we will return fail when apply an answer that doesn't have
1211 // crypto enabled.
1212 TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
1213   Init(NULL);
1214   SessionDescriptionInterface* offer = NULL;
1215   SessionDescriptionInterface* answer = NULL;
1216   CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1217   // SetRemoteDescription and SetLocalDescription will take the ownership of
1218   // the offer.
1219   SetLocalDescriptionWithoutError(offer);
1220   SetRemoteDescriptionAnswerExpectError(kSdpWithoutCrypto, answer);
1221 }
1222
1223 // Test that we can create and set an offer with a DTLS fingerprint.
1224 TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1225   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1226   InitWithDtls();
1227   mediastream_signaling_.SendAudioVideoStream1();
1228   SessionDescriptionInterface* offer = CreateOffer(NULL);
1229   ASSERT_TRUE(offer != NULL);
1230   VerifyFingerprintStatus(offer->description(), true);
1231   // SetLocalDescription will take the ownership of the offer.
1232   SetLocalDescriptionWithoutError(offer);
1233 }
1234
1235 // Test that we can process an offer with a DTLS fingerprint
1236 // and that we return an answer with a fingerprint.
1237 TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1238   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1239   InitWithDtls();
1240   SetFactoryDtlsSrtp();
1241   cricket::MediaSessionOptions options;
1242   options.has_video = true;
1243   JsepSessionDescription* offer = CreateRemoteOffer(options);
1244   ASSERT_TRUE(offer != NULL);
1245   VerifyFingerprintStatus(offer->description(), true);
1246
1247   // SetRemoteDescription will take the ownership of the offer.
1248   SetRemoteDescriptionWithoutError(offer);
1249
1250   // Verify that we get a crypto fingerprint in the answer.
1251   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1252   ASSERT_TRUE(answer != NULL);
1253   VerifyFingerprintStatus(answer->description(), true);
1254   // Check that we don't have an a=crypto line in the answer.
1255   VerifyNoCryptoParams(answer->description(), true);
1256
1257   // Now set the local description, which should work, even without a=crypto.
1258   SetLocalDescriptionWithoutError(answer);
1259 }
1260
1261 // Test that even if we support DTLS, if the other side didn't offer a
1262 // fingerprint, we don't either.
1263 TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1264   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1265   InitWithDtls();
1266   cricket::MediaSessionOptions options;
1267   options.has_video = true;
1268   JsepSessionDescription* offer = CreateRemoteOffer(
1269       options, cricket::SEC_REQUIRED);
1270   ASSERT_TRUE(offer != NULL);
1271   VerifyFingerprintStatus(offer->description(), false);
1272
1273   // SetRemoteDescription will take the ownership of
1274   // the offer.
1275   SetRemoteDescriptionWithoutError(offer);
1276
1277   // Verify that we don't get a crypto fingerprint in the answer.
1278   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1279   ASSERT_TRUE(answer != NULL);
1280   VerifyFingerprintStatus(answer->description(), false);
1281
1282   // Now set the local description.
1283   SetLocalDescriptionWithoutError(answer);
1284 }
1285
1286 TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
1287   Init(NULL);
1288   mediastream_signaling_.SendNothing();
1289   // SetLocalDescription take ownership of offer.
1290   SessionDescriptionInterface* offer = CreateOffer(NULL);
1291   SetLocalDescriptionWithoutError(offer);
1292
1293   // SetLocalDescription take ownership of offer.
1294   SessionDescriptionInterface* offer2 = CreateOffer(NULL);
1295   SetLocalDescriptionWithoutError(offer2);
1296 }
1297
1298 TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
1299   Init(NULL);
1300   mediastream_signaling_.SendNothing();
1301   // SetLocalDescription take ownership of offer.
1302   SessionDescriptionInterface* offer = CreateOffer(NULL);
1303   SetRemoteDescriptionWithoutError(offer);
1304
1305   SessionDescriptionInterface* offer2 = CreateOffer(NULL);
1306   SetRemoteDescriptionWithoutError(offer2);
1307 }
1308
1309 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
1310   Init(NULL);
1311   mediastream_signaling_.SendNothing();
1312   SessionDescriptionInterface* offer = CreateOffer(NULL);
1313   SetLocalDescriptionWithoutError(offer);
1314   offer = CreateOffer(NULL);
1315   SetRemoteDescriptionOfferExpectError(
1316       "Called in wrong state: STATE_SENTINITIATE", offer);
1317 }
1318
1319 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
1320   Init(NULL);
1321   mediastream_signaling_.SendNothing();
1322   SessionDescriptionInterface* offer = CreateOffer(NULL);
1323   SetRemoteDescriptionWithoutError(offer);
1324   offer = CreateOffer(NULL);
1325   SetLocalDescriptionOfferExpectError(
1326       "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
1327 }
1328
1329 TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
1330   Init(NULL);
1331   mediastream_signaling_.SendNothing();
1332   SessionDescriptionInterface* offer = CreateRemoteOffer();
1333   SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1334
1335   JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
1336       CreateAnswer(NULL));
1337   pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1338   SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1339
1340   mediastream_signaling_.SendAudioVideoStream1();
1341   JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
1342       CreateAnswer(NULL));
1343   pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1344
1345   SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1346
1347   mediastream_signaling_.SendAudioVideoStream2();
1348   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1349   SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1350 }
1351
1352 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
1353   Init(NULL);
1354   mediastream_signaling_.SendNothing();
1355   SessionDescriptionInterface* offer = CreateOffer(NULL);
1356   SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1357
1358   JsepSessionDescription* pranswer =
1359       CreateRemoteAnswer(session_->local_description());
1360   pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1361
1362   SetRemoteDescriptionExpectState(pranswer,
1363                                   BaseSession::STATE_RECEIVEDPRACCEPT);
1364
1365   mediastream_signaling_.SendAudioVideoStream1();
1366   JsepSessionDescription* pranswer2 =
1367       CreateRemoteAnswer(session_->local_description());
1368   pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1369
1370   SetRemoteDescriptionExpectState(pranswer2,
1371                                   BaseSession::STATE_RECEIVEDPRACCEPT);
1372
1373   mediastream_signaling_.SendAudioVideoStream2();
1374   SessionDescriptionInterface* answer =
1375       CreateRemoteAnswer(session_->local_description());
1376   SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1377 }
1378
1379 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
1380   Init(NULL);
1381   mediastream_signaling_.SendNothing();
1382   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1383       CreateOffer(NULL));
1384   SessionDescriptionInterface* answer =
1385       CreateRemoteAnswer(offer.get());
1386   SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1387                                        answer);
1388 }
1389
1390 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
1391   Init(NULL);
1392   mediastream_signaling_.SendNothing();
1393   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1394         CreateOffer(NULL));
1395   SessionDescriptionInterface* answer =
1396       CreateRemoteAnswer(offer.get());
1397   SetRemoteDescriptionAnswerExpectError(
1398       "Called in wrong state: STATE_INIT", answer);
1399 }
1400
1401 TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
1402   Init(NULL);
1403   mediastream_signaling_.SendAudioVideoStream1();
1404
1405   cricket::Candidate candidate;
1406   candidate.set_component(1);
1407   JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1408
1409   // Fail since we have not set a offer description.
1410   EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1411
1412   SessionDescriptionInterface* offer = CreateOffer(NULL);
1413   SetLocalDescriptionWithoutError(offer);
1414   // Candidate should be allowed to add before remote description.
1415   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1416   candidate.set_component(2);
1417   JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1418   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1419
1420   SessionDescriptionInterface* answer = CreateRemoteAnswer(
1421       session_->local_description());
1422   SetRemoteDescriptionWithoutError(answer);
1423
1424   // Verifying the candidates are copied properly from internal vector.
1425   const SessionDescriptionInterface* remote_desc =
1426       session_->remote_description();
1427   ASSERT_TRUE(remote_desc != NULL);
1428   ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1429   const IceCandidateCollection* candidates =
1430       remote_desc->candidates(kMediaContentIndex0);
1431   ASSERT_EQ(2u, candidates->count());
1432   EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1433   EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1434   EXPECT_EQ(1, candidates->at(0)->candidate().component());
1435   EXPECT_EQ(2, candidates->at(1)->candidate().component());
1436
1437   // |ice_candidate3| is identical to |ice_candidate2|.  It can be added
1438   // successfully, but the total count of candidates will not increase.
1439   candidate.set_component(2);
1440   JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1441   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1442   ASSERT_EQ(2u, candidates->count());
1443
1444   JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1445   EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1446 }
1447
1448 // Test that a remote candidate is added to the remote session description and
1449 // that it is retained if the remote session description is changed.
1450 TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
1451   Init(NULL);
1452   cricket::Candidate candidate1;
1453   candidate1.set_component(1);
1454   JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1455                                   candidate1);
1456   mediastream_signaling_.SendAudioVideoStream1();
1457   CreateAndSetRemoteOfferAndLocalAnswer();
1458
1459   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1460   const SessionDescriptionInterface* remote_desc =
1461       session_->remote_description();
1462   ASSERT_TRUE(remote_desc != NULL);
1463   ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1464   const IceCandidateCollection* candidates =
1465       remote_desc->candidates(kMediaContentIndex0);
1466   ASSERT_EQ(1u, candidates->count());
1467   EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1468
1469   // Update the RemoteSessionDescription with a new session description and
1470   // a candidate and check that the new remote session description contains both
1471   // candidates.
1472   SessionDescriptionInterface* offer = CreateRemoteOffer();
1473   cricket::Candidate candidate2;
1474   JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1475                                   candidate2);
1476   EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1477   SetRemoteDescriptionWithoutError(offer);
1478
1479   remote_desc = session_->remote_description();
1480   ASSERT_TRUE(remote_desc != NULL);
1481   ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1482   candidates = remote_desc->candidates(kMediaContentIndex0);
1483   ASSERT_EQ(2u, candidates->count());
1484   EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1485   // Username and password have be updated with the TransportInfo of the
1486   // SessionDescription, won't be equal to the original one.
1487   candidate2.set_username(candidates->at(0)->candidate().username());
1488   candidate2.set_password(candidates->at(0)->candidate().password());
1489   EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1490   EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1491   // No need to verify the username and password.
1492   candidate1.set_username(candidates->at(1)->candidate().username());
1493   candidate1.set_password(candidates->at(1)->candidate().password());
1494   EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1495
1496   // Test that the candidate is ignored if we can add the same candidate again.
1497   EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1498 }
1499
1500 // Test that local candidates are added to the local session description and
1501 // that they are retained if the local session description is changed.
1502 TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1503   AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1504   Init(NULL);
1505   mediastream_signaling_.SendAudioVideoStream1();
1506   CreateAndSetRemoteOfferAndLocalAnswer();
1507
1508   const SessionDescriptionInterface* local_desc = session_->local_description();
1509   const IceCandidateCollection* candidates =
1510       local_desc->candidates(kMediaContentIndex0);
1511   ASSERT_TRUE(candidates != NULL);
1512   EXPECT_EQ(0u, candidates->count());
1513
1514   EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1515
1516   local_desc = session_->local_description();
1517   candidates = local_desc->candidates(kMediaContentIndex0);
1518   ASSERT_TRUE(candidates != NULL);
1519   EXPECT_LT(0u, candidates->count());
1520   candidates = local_desc->candidates(1);
1521   ASSERT_TRUE(candidates != NULL);
1522   EXPECT_LT(0u, candidates->count());
1523
1524   // Update the session descriptions.
1525   mediastream_signaling_.SendAudioVideoStream1();
1526   CreateAndSetRemoteOfferAndLocalAnswer();
1527
1528   local_desc = session_->local_description();
1529   candidates = local_desc->candidates(kMediaContentIndex0);
1530   ASSERT_TRUE(candidates != NULL);
1531   EXPECT_LT(0u, candidates->count());
1532   candidates = local_desc->candidates(1);
1533   ASSERT_TRUE(candidates != NULL);
1534   EXPECT_LT(0u, candidates->count());
1535 }
1536
1537 // Test that we can set a remote session description with remote candidates.
1538 TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
1539   Init(NULL);
1540
1541   cricket::Candidate candidate1;
1542   candidate1.set_component(1);
1543   JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1544                                  candidate1);
1545   mediastream_signaling_.SendAudioVideoStream1();
1546   SessionDescriptionInterface* offer = CreateOffer(NULL);
1547
1548   EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1549   SetRemoteDescriptionWithoutError(offer);
1550
1551   const SessionDescriptionInterface* remote_desc =
1552       session_->remote_description();
1553   ASSERT_TRUE(remote_desc != NULL);
1554   ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1555   const IceCandidateCollection* candidates =
1556       remote_desc->candidates(kMediaContentIndex0);
1557   ASSERT_EQ(1u, candidates->count());
1558   EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1559
1560   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1561   SetLocalDescriptionWithoutError(answer);
1562 }
1563
1564 // Test that offers and answers contains ice candidates when Ice candidates have
1565 // been gathered.
1566 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1567   AddInterface(talk_base::SocketAddress(kClientAddrHost1, kClientAddrPort));
1568   Init(NULL);
1569   mediastream_signaling_.SendAudioVideoStream1();
1570   // Ice is started but candidates are not provided until SetLocalDescription
1571   // is called.
1572   EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1573   EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1574   CreateAndSetRemoteOfferAndLocalAnswer();
1575   // Wait until at least one local candidate has been collected.
1576   EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1577                    kIceCandidatesTimeout);
1578   EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1579                    kIceCandidatesTimeout);
1580
1581   talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
1582       CreateOffer(NULL));
1583   ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1584   EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1585   ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1586   EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1587
1588   SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1589   SetRemoteDescriptionWithoutError(remote_offer);
1590   SessionDescriptionInterface* answer = CreateAnswer(NULL);
1591   ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1592   EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1593   ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1594   EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1595   SetLocalDescriptionWithoutError(answer);
1596 }
1597
1598 // Verifies TransportProxy and media channels are created with content names
1599 // present in the SessionDescription.
1600 TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
1601   Init(NULL);
1602   mediastream_signaling_.SendAudioVideoStream1();
1603   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1604       CreateOffer(NULL));
1605
1606   // CreateOffer creates session description with the content names "audio" and
1607   // "video". Goal is to modify these content names and verify transport channel
1608   // proxy in the BaseSession, as proxies are created with the content names
1609   // present in SDP.
1610   std::string sdp;
1611   EXPECT_TRUE(offer->ToString(&sdp));
1612   const std::string kAudioMid = "a=mid:audio";
1613   const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1614   const std::string kVideoMid = "a=mid:video";
1615   const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1616
1617   // Replacing |audio| with |audio_content_name|.
1618   talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1619                              kAudioMidReplaceStr.c_str(),
1620                              kAudioMidReplaceStr.length(),
1621                              &sdp);
1622   // Replacing |video| with |video_content_name|.
1623   talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1624                              kVideoMidReplaceStr.c_str(),
1625                              kVideoMidReplaceStr.length(),
1626                              &sdp);
1627
1628   SessionDescriptionInterface* modified_offer =
1629       CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1630
1631   SetRemoteDescriptionWithoutError(modified_offer);
1632
1633   SessionDescriptionInterface* answer =
1634       CreateAnswer(NULL);
1635   SetLocalDescriptionWithoutError(answer);
1636
1637   EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1638   EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1639   EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1640   EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1641 }
1642
1643 // Test that an offer contains the correct media content descriptions based on
1644 // the send streams when no constraints have been set.
1645 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
1646   Init(NULL);
1647   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1648       CreateOffer(NULL));
1649   ASSERT_TRUE(offer != NULL);
1650   const cricket::ContentInfo* content =
1651       cricket::GetFirstAudioContent(offer->description());
1652   EXPECT_TRUE(content != NULL);
1653   content = cricket::GetFirstVideoContent(offer->description());
1654   EXPECT_TRUE(content == NULL);
1655 }
1656
1657 // Test that an offer contains the correct media content descriptions based on
1658 // the send streams when no constraints have been set.
1659 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
1660   Init(NULL);
1661   // Test Audio only offer.
1662   mediastream_signaling_.UseOptionsAudioOnly();
1663   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1664         CreateOffer(NULL));
1665   const cricket::ContentInfo* content =
1666       cricket::GetFirstAudioContent(offer->description());
1667   EXPECT_TRUE(content != NULL);
1668   content = cricket::GetFirstVideoContent(offer->description());
1669   EXPECT_TRUE(content == NULL);
1670
1671   // Test Audio / Video offer.
1672   mediastream_signaling_.SendAudioVideoStream1();
1673   offer.reset(CreateOffer(NULL));
1674   content = cricket::GetFirstAudioContent(offer->description());
1675   EXPECT_TRUE(content != NULL);
1676   content = cricket::GetFirstVideoContent(offer->description());
1677   EXPECT_TRUE(content != NULL);
1678 }
1679
1680 // Test that an offer contains no media content descriptions if
1681 // kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1682 TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
1683   Init(NULL);
1684   webrtc::FakeConstraints constraints_no_receive;
1685   constraints_no_receive.SetMandatoryReceiveAudio(false);
1686   constraints_no_receive.SetMandatoryReceiveVideo(false);
1687
1688   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1689       CreateOffer(&constraints_no_receive));
1690   ASSERT_TRUE(offer != NULL);
1691   const cricket::ContentInfo* content =
1692       cricket::GetFirstAudioContent(offer->description());
1693   EXPECT_TRUE(content == NULL);
1694   content = cricket::GetFirstVideoContent(offer->description());
1695   EXPECT_TRUE(content == NULL);
1696 }
1697
1698 // Test that an offer contains only audio media content descriptions if
1699 // kOfferToReceiveAudio constraints are set to true.
1700 TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
1701   Init(NULL);
1702   webrtc::FakeConstraints constraints_audio_only;
1703   constraints_audio_only.SetMandatoryReceiveAudio(true);
1704   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1705         CreateOffer(&constraints_audio_only));
1706
1707   const cricket::ContentInfo* content =
1708       cricket::GetFirstAudioContent(offer->description());
1709   EXPECT_TRUE(content != NULL);
1710   content = cricket::GetFirstVideoContent(offer->description());
1711   EXPECT_TRUE(content == NULL);
1712 }
1713
1714 // Test that an offer contains audio and video media content descriptions if
1715 // kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1716 TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
1717   Init(NULL);
1718   // Test Audio / Video offer.
1719   webrtc::FakeConstraints constraints_audio_video;
1720   constraints_audio_video.SetMandatoryReceiveAudio(true);
1721   constraints_audio_video.SetMandatoryReceiveVideo(true);
1722   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1723       CreateOffer(&constraints_audio_video));
1724   const cricket::ContentInfo* content =
1725       cricket::GetFirstAudioContent(offer->description());
1726
1727   EXPECT_TRUE(content != NULL);
1728   content = cricket::GetFirstVideoContent(offer->description());
1729   EXPECT_TRUE(content != NULL);
1730
1731   // TODO(perkj): Should the direction be set to SEND_ONLY if
1732   // The constraints is set to not receive audio or video but a track is added?
1733 }
1734
1735 // Test that an answer can not be created if the last remote description is not
1736 // an offer.
1737 TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
1738   Init(NULL);
1739   SessionDescriptionInterface* offer = CreateOffer(NULL);
1740   SetLocalDescriptionWithoutError(offer);
1741   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1742   SetRemoteDescriptionWithoutError(answer);
1743   EXPECT_TRUE(CreateAnswer(NULL) == NULL);
1744 }
1745
1746 // Test that an answer contains the correct media content descriptions when no
1747 // constraints have been set.
1748 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
1749   Init(NULL);
1750   // Create a remote offer with audio and video content.
1751   talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1752   SetRemoteDescriptionWithoutError(offer.release());
1753   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1754       CreateAnswer(NULL));
1755   const cricket::ContentInfo* content =
1756       cricket::GetFirstAudioContent(answer->description());
1757   ASSERT_TRUE(content != NULL);
1758   EXPECT_FALSE(content->rejected);
1759
1760   content = cricket::GetFirstVideoContent(answer->description());
1761   ASSERT_TRUE(content != NULL);
1762   EXPECT_FALSE(content->rejected);
1763 }
1764
1765 // Test that an answer contains the correct media content descriptions when no
1766 // constraints have been set and the offer only contain audio.
1767 TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
1768   Init(NULL);
1769   // Create a remote offer with audio only.
1770   cricket::MediaSessionOptions options;
1771   options.has_audio = true;
1772   options.has_video = false;
1773   talk_base::scoped_ptr<JsepSessionDescription> offer(
1774       CreateRemoteOffer(options));
1775   ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1776   ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1777
1778   SetRemoteDescriptionWithoutError(offer.release());
1779   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1780       CreateAnswer(NULL));
1781   const cricket::ContentInfo* content =
1782       cricket::GetFirstAudioContent(answer->description());
1783   ASSERT_TRUE(content != NULL);
1784   EXPECT_FALSE(content->rejected);
1785
1786   EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1787 }
1788
1789 // Test that an answer contains the correct media content descriptions when no
1790 // constraints have been set.
1791 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
1792   Init(NULL);
1793   // Create a remote offer with audio and video content.
1794   talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1795   SetRemoteDescriptionWithoutError(offer.release());
1796   // Test with a stream with tracks.
1797   mediastream_signaling_.SendAudioVideoStream1();
1798   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1799       CreateAnswer(NULL));
1800   const cricket::ContentInfo* content =
1801       cricket::GetFirstAudioContent(answer->description());
1802   ASSERT_TRUE(content != NULL);
1803   EXPECT_FALSE(content->rejected);
1804
1805   content = cricket::GetFirstVideoContent(answer->description());
1806   ASSERT_TRUE(content != NULL);
1807   EXPECT_FALSE(content->rejected);
1808 }
1809
1810 // Test that an answer contains the correct media content descriptions when
1811 // constraints have been set but no stream is sent.
1812 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
1813   Init(NULL);
1814   // Create a remote offer with audio and video content.
1815   talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1816   SetRemoteDescriptionWithoutError(offer.release());
1817
1818   webrtc::FakeConstraints constraints_no_receive;
1819   constraints_no_receive.SetMandatoryReceiveAudio(false);
1820   constraints_no_receive.SetMandatoryReceiveVideo(false);
1821
1822   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1823       CreateAnswer(&constraints_no_receive));
1824   const cricket::ContentInfo* content =
1825       cricket::GetFirstAudioContent(answer->description());
1826   ASSERT_TRUE(content != NULL);
1827   EXPECT_TRUE(content->rejected);
1828
1829   content = cricket::GetFirstVideoContent(answer->description());
1830   ASSERT_TRUE(content != NULL);
1831   EXPECT_TRUE(content->rejected);
1832 }
1833
1834 // Test that an answer contains the correct media content descriptions when
1835 // constraints have been set and streams are sent.
1836 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
1837   Init(NULL);
1838   // Create a remote offer with audio and video content.
1839   talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1840   SetRemoteDescriptionWithoutError(offer.release());
1841
1842   webrtc::FakeConstraints constraints_no_receive;
1843   constraints_no_receive.SetMandatoryReceiveAudio(false);
1844   constraints_no_receive.SetMandatoryReceiveVideo(false);
1845
1846   // Test with a stream with tracks.
1847   mediastream_signaling_.SendAudioVideoStream1();
1848   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1849       CreateAnswer(&constraints_no_receive));
1850
1851   // TODO(perkj): Should the direction be set to SEND_ONLY?
1852   const cricket::ContentInfo* content =
1853       cricket::GetFirstAudioContent(answer->description());
1854   ASSERT_TRUE(content != NULL);
1855   EXPECT_FALSE(content->rejected);
1856
1857   // TODO(perkj): Should the direction be set to SEND_ONLY?
1858   content = cricket::GetFirstVideoContent(answer->description());
1859   ASSERT_TRUE(content != NULL);
1860   EXPECT_FALSE(content->rejected);
1861 }
1862
1863 TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1864   AddCNCodecs();
1865   Init(NULL);
1866   webrtc::FakeConstraints constraints;
1867   constraints.SetOptionalVAD(false);
1868   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1869       CreateOffer(&constraints));
1870   const cricket::ContentInfo* content =
1871       cricket::GetFirstAudioContent(offer->description());
1872   EXPECT_TRUE(content != NULL);
1873   EXPECT_TRUE(VerifyNoCNCodecs(content));
1874 }
1875
1876 TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1877   AddCNCodecs();
1878   Init(NULL);
1879   // Create a remote offer with audio and video content.
1880   talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1881   SetRemoteDescriptionWithoutError(offer.release());
1882
1883   webrtc::FakeConstraints constraints;
1884   constraints.SetOptionalVAD(false);
1885   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1886       CreateAnswer(&constraints));
1887   const cricket::ContentInfo* content =
1888       cricket::GetFirstAudioContent(answer->description());
1889   ASSERT_TRUE(content != NULL);
1890   EXPECT_TRUE(VerifyNoCNCodecs(content));
1891 }
1892
1893 // This test verifies the call setup when remote answer with audio only and
1894 // later updates with video.
1895 TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
1896   Init(NULL);
1897   EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1898   EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1899
1900   mediastream_signaling_.SendAudioVideoStream1();
1901   SessionDescriptionInterface* offer = CreateOffer(NULL);
1902
1903   cricket::MediaSessionOptions options;
1904   options.has_video = false;
1905   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1906
1907   // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1908   // and answer;
1909   SetLocalDescriptionWithoutError(offer);
1910   SetRemoteDescriptionWithoutError(answer);
1911
1912   video_channel_ = media_engine_->GetVideoChannel(0);
1913   voice_channel_ = media_engine_->GetVoiceChannel(0);
1914
1915   ASSERT_TRUE(video_channel_ == NULL);
1916
1917   ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1918   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1919   EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1920
1921   // Let the remote end update the session descriptions, with Audio and Video.
1922   mediastream_signaling_.SendAudioVideoStream2();
1923   CreateAndSetRemoteOfferAndLocalAnswer();
1924
1925   video_channel_ = media_engine_->GetVideoChannel(0);
1926   voice_channel_ = media_engine_->GetVoiceChannel(0);
1927
1928   ASSERT_TRUE(video_channel_ != NULL);
1929   ASSERT_TRUE(voice_channel_ != NULL);
1930
1931   ASSERT_EQ(1u, video_channel_->recv_streams().size());
1932   ASSERT_EQ(1u, video_channel_->send_streams().size());
1933   EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1934   EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1935   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1936   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1937   EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1938   EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1939
1940   // Change session back to audio only.
1941   mediastream_signaling_.UseOptionsAudioOnly();
1942   CreateAndSetRemoteOfferAndLocalAnswer();
1943
1944   EXPECT_EQ(0u, video_channel_->recv_streams().size());
1945   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1946   EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1947   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1948   EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1949 }
1950
1951 // This test verifies the call setup when remote answer with video only and
1952 // later updates with audio.
1953 TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
1954   Init(NULL);
1955   EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1956   EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1957   mediastream_signaling_.SendAudioVideoStream1();
1958   SessionDescriptionInterface* offer = CreateOffer(NULL);
1959
1960   cricket::MediaSessionOptions options;
1961   options.has_audio = false;
1962   options.has_video = true;
1963   SessionDescriptionInterface* answer = CreateRemoteAnswer(
1964       offer, options, cricket::SEC_ENABLED);
1965
1966   // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1967   // and answer.
1968   SetLocalDescriptionWithoutError(offer);
1969   SetRemoteDescriptionWithoutError(answer);
1970
1971   video_channel_ = media_engine_->GetVideoChannel(0);
1972   voice_channel_ = media_engine_->GetVoiceChannel(0);
1973
1974   ASSERT_TRUE(voice_channel_ == NULL);
1975   ASSERT_TRUE(video_channel_ != NULL);
1976
1977   EXPECT_EQ(0u, video_channel_->recv_streams().size());
1978   ASSERT_EQ(1u, video_channel_->send_streams().size());
1979   EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1980
1981   // Update the session descriptions, with Audio and Video.
1982   mediastream_signaling_.SendAudioVideoStream2();
1983   CreateAndSetRemoteOfferAndLocalAnswer();
1984
1985   voice_channel_ = media_engine_->GetVoiceChannel(0);
1986   ASSERT_TRUE(voice_channel_ != NULL);
1987
1988   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1989   ASSERT_EQ(1u, voice_channel_->send_streams().size());
1990   EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1991   EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1992
1993   // Change session back to video only.
1994   mediastream_signaling_.UseOptionsVideoOnly();
1995   CreateAndSetRemoteOfferAndLocalAnswer();
1996
1997   video_channel_ = media_engine_->GetVideoChannel(0);
1998   voice_channel_ = media_engine_->GetVoiceChannel(0);
1999
2000   ASSERT_EQ(1u, video_channel_->recv_streams().size());
2001   EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2002   ASSERT_EQ(1u, video_channel_->send_streams().size());
2003   EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2004 }
2005
2006 TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
2007   Init(NULL);
2008   mediastream_signaling_.SendAudioVideoStream1();
2009   scoped_ptr<SessionDescriptionInterface> offer(
2010       CreateOffer(NULL));
2011   VerifyCryptoParams(offer->description());
2012   SetRemoteDescriptionWithoutError(offer.release());
2013   scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2014   VerifyCryptoParams(answer->description());
2015 }
2016
2017 TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
2018   options_.disable_encryption = true;
2019   Init(NULL);
2020   mediastream_signaling_.SendAudioVideoStream1();
2021   scoped_ptr<SessionDescriptionInterface> offer(
2022         CreateOffer(NULL));
2023   VerifyNoCryptoParams(offer->description(), false);
2024 }
2025
2026 TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
2027   Init(NULL);
2028   VerifyAnswerFromNonCryptoOffer();
2029 }
2030
2031 TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
2032   Init(NULL);
2033   VerifyAnswerFromCryptoOffer();
2034 }
2035
2036 // This test verifies that setLocalDescription fails if
2037 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2038 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
2039   Init(NULL);
2040   mediastream_signaling_.SendAudioVideoStream1();
2041   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2042   std::string sdp;
2043   RemoveIceUfragPwdLines(offer.get(), &sdp);
2044   SessionDescriptionInterface* modified_offer =
2045     CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2046   SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
2047 }
2048
2049 // This test verifies that setRemoteDescription fails if
2050 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2051 TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
2052   Init(NULL);
2053   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
2054   std::string sdp;
2055   RemoveIceUfragPwdLines(offer.get(), &sdp);
2056   SessionDescriptionInterface* modified_offer =
2057     CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2058   SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
2059 }
2060
2061 TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
2062   // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
2063   // local description is removed by the application, BUNDLE flag should be
2064   // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
2065   Init(NULL);
2066   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
2067       cricket::PORTALLOCATOR_ENABLE_BUNDLE);
2068   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2069       CreateOffer(NULL));
2070   cricket::SessionDescription* offer_copy =
2071       offer->description()->Copy();
2072   offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2073   JsepSessionDescription* modified_offer =
2074       new JsepSessionDescription(JsepSessionDescription::kOffer);
2075   modified_offer->Initialize(offer_copy, "1", "1");
2076
2077   SetLocalDescriptionWithoutError(modified_offer);
2078   EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
2079 }
2080
2081 TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
2082   Init(NULL);
2083   mediastream_signaling_.SendAudioVideoStream1();
2084   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
2085       cricket::PORTALLOCATOR_ENABLE_BUNDLE);
2086   FakeConstraints constraints;
2087   constraints.SetMandatoryUseRtpMux(true);
2088   SessionDescriptionInterface* offer = CreateOffer(&constraints);
2089   SetLocalDescriptionWithoutError(offer);
2090   mediastream_signaling_.SendAudioVideoStream2();
2091   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2092       CreateRemoteAnswer(session_->local_description()));
2093   cricket::SessionDescription* answer_copy = answer->description()->Copy();
2094   answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2095   JsepSessionDescription* modified_answer =
2096       new JsepSessionDescription(JsepSessionDescription::kAnswer);
2097   modified_answer->Initialize(answer_copy, "1", "1");
2098   SetRemoteDescriptionWithoutError(modified_answer);
2099   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
2100       cricket::PORTALLOCATOR_ENABLE_BUNDLE);
2101
2102   video_channel_ = media_engine_->GetVideoChannel(0);
2103   voice_channel_ = media_engine_->GetVoiceChannel(0);
2104
2105   ASSERT_EQ(1u, video_channel_->recv_streams().size());
2106   EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
2107
2108   ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2109   EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
2110
2111   ASSERT_EQ(1u, video_channel_->send_streams().size());
2112   EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
2113   ASSERT_EQ(1u, voice_channel_->send_streams().size());
2114   EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
2115 }
2116
2117 // This test verifies that SetLocalDescription and SetRemoteDescription fails
2118 // if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2119 TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
2120   WebRtcSessionTest::Init(NULL);
2121   mediastream_signaling_.SendAudioVideoStream1();
2122   EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
2123       cricket::PORTALLOCATOR_ENABLE_BUNDLE);
2124   FakeConstraints constraints;
2125   constraints.SetMandatoryUseRtpMux(true);
2126   SessionDescriptionInterface* offer = CreateOffer(&constraints);
2127   std::string offer_str;
2128   offer->ToString(&offer_str);
2129   // Disable rtcp-mux
2130   const std::string rtcp_mux = "rtcp-mux";
2131   const std::string xrtcp_mux = "xrtcp-mux";
2132   talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
2133                              xrtcp_mux.c_str(), xrtcp_mux.length(),
2134                              &offer_str);
2135   JsepSessionDescription *local_offer =
2136       new JsepSessionDescription(JsepSessionDescription::kOffer);
2137   EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
2138   SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
2139   JsepSessionDescription *remote_offer =
2140       new JsepSessionDescription(JsepSessionDescription::kOffer);
2141   EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
2142   SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
2143   // Trying unmodified SDP.
2144   SetLocalDescriptionWithoutError(offer);
2145 }
2146
2147 TEST_F(WebRtcSessionTest, SetAudioPlayout) {
2148   Init(NULL);
2149   mediastream_signaling_.SendAudioVideoStream1();
2150   CreateAndSetRemoteOfferAndLocalAnswer();
2151   cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2152   ASSERT_TRUE(channel != NULL);
2153   ASSERT_EQ(1u, channel->recv_streams().size());
2154   uint32 receive_ssrc  = channel->recv_streams()[0].first_ssrc();
2155   double left_vol, right_vol;
2156   EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2157   EXPECT_EQ(1, left_vol);
2158   EXPECT_EQ(1, right_vol);
2159   talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2160   session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
2161   EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2162   EXPECT_EQ(0, left_vol);
2163   EXPECT_EQ(0, right_vol);
2164   EXPECT_EQ(0, renderer->channel_id());
2165   session_->SetAudioPlayout(receive_ssrc, true, NULL);
2166   EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2167   EXPECT_EQ(1, left_vol);
2168   EXPECT_EQ(1, right_vol);
2169   EXPECT_EQ(-1, renderer->channel_id());
2170 }
2171
2172 TEST_F(WebRtcSessionTest, SetAudioSend) {
2173   Init(NULL);
2174   mediastream_signaling_.SendAudioVideoStream1();
2175   CreateAndSetRemoteOfferAndLocalAnswer();
2176   cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2177   ASSERT_TRUE(channel != NULL);
2178   ASSERT_EQ(1u, channel->send_streams().size());
2179   uint32 send_ssrc  = channel->send_streams()[0].first_ssrc();
2180   EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2181
2182   cricket::AudioOptions options;
2183   options.echo_cancellation.Set(true);
2184
2185   talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2186   session_->SetAudioSend(send_ssrc, false, options, renderer.get());
2187   EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2188   EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
2189   EXPECT_EQ(0, renderer->channel_id());
2190
2191   session_->SetAudioSend(send_ssrc, true, options, NULL);
2192   EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2193   bool value;
2194   EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2195   EXPECT_TRUE(value);
2196   EXPECT_EQ(-1, renderer->channel_id());
2197 }
2198
2199 TEST_F(WebRtcSessionTest, SetVideoPlayout) {
2200   Init(NULL);
2201   mediastream_signaling_.SendAudioVideoStream1();
2202   CreateAndSetRemoteOfferAndLocalAnswer();
2203   cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2204   ASSERT_TRUE(channel != NULL);
2205   ASSERT_LT(0u, channel->renderers().size());
2206   EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2207   ASSERT_EQ(1u, channel->recv_streams().size());
2208   uint32 receive_ssrc  = channel->recv_streams()[0].first_ssrc();
2209   cricket::FakeVideoRenderer renderer;
2210   session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2211   EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2212   session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2213   EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2214 }
2215
2216 TEST_F(WebRtcSessionTest, SetVideoSend) {
2217   Init(NULL);
2218   mediastream_signaling_.SendAudioVideoStream1();
2219   CreateAndSetRemoteOfferAndLocalAnswer();
2220   cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2221   ASSERT_TRUE(channel != NULL);
2222   ASSERT_EQ(1u, channel->send_streams().size());
2223   uint32 send_ssrc  = channel->send_streams()[0].first_ssrc();
2224   EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2225   cricket::VideoOptions* options = NULL;
2226   session_->SetVideoSend(send_ssrc, false, options);
2227   EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2228   session_->SetVideoSend(send_ssrc, true, options);
2229   EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2230 }
2231
2232 TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2233   TestCanInsertDtmf(false);
2234 }
2235
2236 TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2237   TestCanInsertDtmf(true);
2238 }
2239
2240 TEST_F(WebRtcSessionTest, InsertDtmf) {
2241   // Setup
2242   Init(NULL);
2243   mediastream_signaling_.SendAudioVideoStream1();
2244   CreateAndSetRemoteOfferAndLocalAnswer();
2245   FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2246   EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2247
2248   // Insert DTMF
2249   const int expected_flags = DF_SEND;
2250   const int expected_duration = 90;
2251   session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2252   session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2253   session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2254
2255   // Verify
2256   ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2257   const uint32 send_ssrc  = channel->send_streams()[0].first_ssrc();
2258   EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2259                               expected_duration, expected_flags));
2260   EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2261                               expected_duration, expected_flags));
2262   EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2263                               expected_duration, expected_flags));
2264 }
2265
2266 // This test verifies the |initiator| flag when session initiates the call.
2267 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
2268   Init(NULL);
2269   EXPECT_FALSE(session_->initiator());
2270   SessionDescriptionInterface* offer = CreateOffer(NULL);
2271   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2272   SetLocalDescriptionWithoutError(offer);
2273   EXPECT_TRUE(session_->initiator());
2274   SetRemoteDescriptionWithoutError(answer);
2275   EXPECT_TRUE(session_->initiator());
2276 }
2277
2278 // This test verifies the |initiator| flag when session receives the call.
2279 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
2280   Init(NULL);
2281   EXPECT_FALSE(session_->initiator());
2282   SessionDescriptionInterface* offer = CreateRemoteOffer();
2283   SetRemoteDescriptionWithoutError(offer);
2284   SessionDescriptionInterface* answer = CreateAnswer(NULL);
2285
2286   EXPECT_FALSE(session_->initiator());
2287   SetLocalDescriptionWithoutError(answer);
2288   EXPECT_FALSE(session_->initiator());
2289 }
2290
2291 // This test verifies the ice protocol type at initiator of the call
2292 // if |a=ice-options:google-ice| is present in answer.
2293 TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
2294   Init(NULL);
2295   mediastream_signaling_.SendAudioVideoStream1();
2296   SessionDescriptionInterface* offer = CreateOffer(NULL);
2297   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2298       CreateRemoteAnswer(offer));
2299   SetLocalDescriptionWithoutError(offer);
2300   std::string sdp;
2301   EXPECT_TRUE(answer->ToString(&sdp));
2302   // Adding ice-options to the session level.
2303   InjectAfter("t=0 0\r\n",
2304               "a=ice-options:google-ice\r\n",
2305               &sdp);
2306   SessionDescriptionInterface* answer_with_gice =
2307       CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2308   SetRemoteDescriptionWithoutError(answer_with_gice);
2309   VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2310   VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2311 }
2312
2313 // This test verifies the ice protocol type at initiator of the call
2314 // if ICE RFC5245 is supported in answer.
2315 TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
2316   Init(NULL);
2317   mediastream_signaling_.SendAudioVideoStream1();
2318   SessionDescriptionInterface* offer = CreateOffer(NULL);
2319   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2320   SetLocalDescriptionWithoutError(offer);
2321
2322   SetRemoteDescriptionWithoutError(answer);
2323   VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2324   VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2325 }
2326
2327 // This test verifies the ice protocol type at receiver side of the call if
2328 // receiver decides to use google-ice.
2329 TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
2330   Init(NULL);
2331   mediastream_signaling_.SendAudioVideoStream1();
2332   SessionDescriptionInterface* offer = CreateOffer(NULL);
2333   SetRemoteDescriptionWithoutError(offer);
2334   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2335       CreateAnswer(NULL));
2336   std::string sdp;
2337   EXPECT_TRUE(answer->ToString(&sdp));
2338   // Adding ice-options to the session level.
2339   InjectAfter("t=0 0\r\n",
2340               "a=ice-options:google-ice\r\n",
2341               &sdp);
2342   SessionDescriptionInterface* answer_with_gice =
2343       CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2344   SetLocalDescriptionWithoutError(answer_with_gice);
2345   VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2346   VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2347 }
2348
2349 // This test verifies the ice protocol type at receiver side of the call if
2350 // receiver decides to use ice RFC 5245.
2351 TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
2352   Init(NULL);
2353   mediastream_signaling_.SendAudioVideoStream1();
2354   SessionDescriptionInterface* offer = CreateOffer(NULL);
2355   SetRemoteDescriptionWithoutError(offer);
2356   SessionDescriptionInterface* answer = CreateAnswer(NULL);
2357   SetLocalDescriptionWithoutError(answer);
2358   VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2359   VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2360 }
2361
2362 // This test verifies the session state when ICE RFC5245 in offer and
2363 // ICE google-ice in answer.
2364 TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
2365   Init(NULL);
2366   mediastream_signaling_.SendAudioVideoStream1();
2367   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2368       CreateOffer(NULL));
2369   std::string offer_str;
2370   offer->ToString(&offer_str);
2371   // Disable google-ice
2372   const std::string gice_option = "google-ice";
2373   const std::string xgoogle_xice = "xgoogle-xice";
2374   talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2375                              xgoogle_xice.c_str(), xgoogle_xice.length(),
2376                              &offer_str);
2377   JsepSessionDescription *ice_only_offer =
2378       new JsepSessionDescription(JsepSessionDescription::kOffer);
2379   EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2380   SetLocalDescriptionWithoutError(ice_only_offer);
2381   std::string original_offer_sdp;
2382   EXPECT_TRUE(offer->ToString(&original_offer_sdp));
2383   SessionDescriptionInterface* pranswer_with_gice =
2384       CreateSessionDescription(JsepSessionDescription::kPrAnswer,
2385                                original_offer_sdp, NULL);
2386   SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
2387                                           pranswer_with_gice);
2388   SessionDescriptionInterface* answer_with_gice =
2389       CreateSessionDescription(JsepSessionDescription::kAnswer,
2390                                original_offer_sdp, NULL);
2391   SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
2392                                         answer_with_gice);
2393 }
2394
2395 // Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2396 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
2397   Init(NULL);
2398   mediastream_signaling_.SendAudioVideoStream1();
2399   SessionDescriptionInterface* offer = CreateOffer(NULL);
2400   SetLocalDescriptionWithoutError(offer);
2401   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2402       CreateRemoteAnswer(session_->local_description()));
2403
2404   cricket::SessionDescription* answer_copy = answer->description()->Copy();
2405   answer_copy->RemoveContentByName("video");
2406   JsepSessionDescription* modified_answer =
2407       new JsepSessionDescription(JsepSessionDescription::kAnswer);
2408
2409   EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2410                                           answer->session_id(),
2411                                           answer->session_version()));
2412   SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
2413
2414   // Modifying content names.
2415   std::string sdp;
2416   EXPECT_TRUE(answer->ToString(&sdp));
2417   const std::string kAudioMid = "a=mid:audio";
2418   const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2419
2420   // Replacing |audio| with |audio_content_name|.
2421   talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2422                              kAudioMidReplaceStr.c_str(),
2423                              kAudioMidReplaceStr.length(),
2424                              &sdp);
2425
2426   SessionDescriptionInterface* modified_answer1 =
2427       CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2428   SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
2429
2430   SetRemoteDescriptionWithoutError(answer.release());
2431 }
2432
2433 // Verifying remote offer and local answer have matching m-lines as per
2434 // RFC 3264.
2435 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
2436   Init(NULL);
2437   mediastream_signaling_.SendAudioVideoStream1();
2438   SessionDescriptionInterface* offer = CreateRemoteOffer();
2439   SetRemoteDescriptionWithoutError(offer);
2440   SessionDescriptionInterface* answer = CreateAnswer(NULL);
2441
2442   cricket::SessionDescription* answer_copy = answer->description()->Copy();
2443   answer_copy->RemoveContentByName("video");
2444   JsepSessionDescription* modified_answer =
2445       new JsepSessionDescription(JsepSessionDescription::kAnswer);
2446
2447   EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2448                                           answer->session_id(),
2449                                           answer->session_version()));
2450   SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
2451   SetLocalDescriptionWithoutError(answer);
2452 }
2453
2454 // This test verifies that WebRtcSession does not start candidate allocation
2455 // before SetLocalDescription is called.
2456 TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
2457   Init(NULL);
2458   mediastream_signaling_.SendAudioVideoStream1();
2459   SessionDescriptionInterface* offer = CreateRemoteOffer();
2460   cricket::Candidate candidate;
2461   candidate.set_component(1);
2462   JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2463                                  candidate);
2464   EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2465   cricket::Candidate candidate1;
2466   candidate1.set_component(1);
2467   JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2468                                   candidate1);
2469   EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2470   SetRemoteDescriptionWithoutError(offer);
2471   ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2472   ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2473
2474   // Pump for 1 second and verify that no candidates are generated.
2475   talk_base::Thread::Current()->ProcessMessages(1000);
2476   EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2477   EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2478
2479   SessionDescriptionInterface* answer = CreateAnswer(NULL);
2480   SetLocalDescriptionWithoutError(answer);
2481   EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2482   EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2483   EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2484 }
2485
2486 // This test verifies that crypto parameter is updated in local session
2487 // description as per security policy set in MediaSessionDescriptionFactory.
2488 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
2489   Init(NULL);
2490   mediastream_signaling_.SendAudioVideoStream1();
2491   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2492       CreateOffer(NULL));
2493
2494   // Making sure SetLocalDescription correctly sets crypto value in
2495   // SessionDescription object after de-serialization of sdp string. The value
2496   // will be set as per MediaSessionDescriptionFactory.
2497   std::string offer_str;
2498   offer->ToString(&offer_str);
2499   SessionDescriptionInterface* jsep_offer_str =
2500       CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2501   SetLocalDescriptionWithoutError(jsep_offer_str);
2502   EXPECT_TRUE(session_->voice_channel()->secure_required());
2503   EXPECT_TRUE(session_->video_channel()->secure_required());
2504 }
2505
2506 // This test verifies the crypto parameter when security is disabled.
2507 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
2508   options_.disable_encryption = true;
2509   Init(NULL);
2510   mediastream_signaling_.SendAudioVideoStream1();
2511   talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2512       CreateOffer(NULL));
2513
2514   // Making sure SetLocalDescription correctly sets crypto value in
2515   // SessionDescription object after de-serialization of sdp string. The value
2516   // will be set as per MediaSessionDescriptionFactory.
2517   std::string offer_str;
2518   offer->ToString(&offer_str);
2519   SessionDescriptionInterface *jsep_offer_str =
2520       CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2521   SetLocalDescriptionWithoutError(jsep_offer_str);
2522   EXPECT_FALSE(session_->voice_channel()->secure_required());
2523   EXPECT_FALSE(session_->video_channel()->secure_required());
2524 }
2525
2526 // This test verifies that an answer contains new ufrag and password if an offer
2527 // with new ufrag and password is received.
2528 TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
2529   Init(NULL);
2530   cricket::MediaSessionOptions options;
2531   options.has_audio = true;
2532   options.has_video = true;
2533   talk_base::scoped_ptr<JsepSessionDescription> offer(
2534       CreateRemoteOffer(options));
2535   SetRemoteDescriptionWithoutError(offer.release());
2536
2537   mediastream_signaling_.SendAudioVideoStream1();
2538   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2539       CreateAnswer(NULL));
2540   SetLocalDescriptionWithoutError(answer.release());
2541
2542   // Receive an offer with new ufrag and password.
2543   options.transport_options.ice_restart = true;
2544   talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
2545       CreateRemoteOffer(options, session_->remote_description()));
2546   SetRemoteDescriptionWithoutError(updated_offer1.release());
2547
2548   talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
2549       CreateAnswer(NULL));
2550
2551   CompareIceUfragAndPassword(updated_answer1->description(),
2552                              session_->local_description()->description(),
2553                              false);
2554
2555   SetLocalDescriptionWithoutError(updated_answer1.release());
2556 }
2557
2558 // This test verifies that an answer contains old ufrag and password if an offer
2559 // with old ufrag and password is received.
2560 TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2561   Init(NULL);
2562   cricket::MediaSessionOptions options;
2563   options.has_audio = true;
2564   options.has_video = true;
2565   talk_base::scoped_ptr<JsepSessionDescription> offer(
2566       CreateRemoteOffer(options));
2567   SetRemoteDescriptionWithoutError(offer.release());
2568
2569   mediastream_signaling_.SendAudioVideoStream1();
2570   talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2571       CreateAnswer(NULL));
2572   SetLocalDescriptionWithoutError(answer.release());
2573
2574   // Receive an offer without changed ufrag or password.
2575   options.transport_options.ice_restart = false;
2576   talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
2577       CreateRemoteOffer(options, session_->remote_description()));
2578   SetRemoteDescriptionWithoutError(updated_offer2.release());
2579
2580   talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
2581       CreateAnswer(NULL));
2582
2583   CompareIceUfragAndPassword(updated_answer2->description(),
2584                              session_->local_description()->description(),
2585                              true);
2586
2587   SetLocalDescriptionWithoutError(updated_answer2.release());
2588 }
2589
2590 TEST_F(WebRtcSessionTest, TestSessionContentError) {
2591   Init(NULL);
2592   mediastream_signaling_.SendAudioVideoStream1();
2593   SessionDescriptionInterface* offer = CreateOffer(NULL);
2594   const std::string session_id_orig = offer->session_id();
2595   const std::string session_version_orig = offer->session_version();
2596   SetLocalDescriptionWithoutError(offer);
2597
2598   video_channel_ = media_engine_->GetVideoChannel(0);
2599   video_channel_->set_fail_set_send_codecs(true);
2600
2601   mediastream_signaling_.SendAudioVideoStream2();
2602   SessionDescriptionInterface* answer =
2603       CreateRemoteAnswer(session_->local_description());
2604   SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
2605 }
2606
2607 // Runs the loopback call test with BUNDLE and STUN disabled.
2608 TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2609   // Lets try with only UDP ports.
2610   allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2611                        cricket::PORTALLOCATOR_DISABLE_TCP |
2612                        cricket::PORTALLOCATOR_DISABLE_STUN |
2613                        cricket::PORTALLOCATOR_DISABLE_RELAY);
2614   TestLoopbackCall();
2615 }
2616
2617 // Runs the loopback call test with BUNDLE, STUN, and TCP enabled.
2618 TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
2619   allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2620                        cricket::PORTALLOCATOR_ENABLE_BUNDLE |
2621                        cricket::PORTALLOCATOR_DISABLE_RELAY);
2622   TestLoopbackCall();
2623 }
2624
2625 TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
2626   Init(NULL);
2627   cricket::MediaSessionOptions options;
2628   options.has_audio = true;
2629   options.has_video = true;
2630
2631   cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
2632   std::string error_code_str = "ERROR_CONTENT";
2633   std::string error_desc = "Fake session error description.";
2634   session_->SetError(error_code, error_desc);
2635
2636   SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2637   SessionDescriptionInterface* answer =
2638       CreateRemoteAnswer(offer, options);
2639
2640   std::string action;
2641   std::ostringstream session_error_msg;
2642   session_error_msg << kSessionError << error_code_str << ". ";
2643   session_error_msg << kSessionErrorDesc << error_desc << ".";
2644   SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
2645   SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
2646 }
2647
2648 TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2649   constraints_.reset(new FakeConstraints());
2650   constraints_->AddOptional(
2651       webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2652   Init(NULL);
2653
2654   SetLocalDescriptionWithDataChannel();
2655   EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2656 }
2657
2658 TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2659   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2660
2661   constraints_.reset(new FakeConstraints());
2662   constraints_->AddOptional(
2663       webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2664   options_.disable_sctp_data_channels = false;
2665
2666   InitWithDtls(false);
2667
2668   SetLocalDescriptionWithDataChannel();
2669   EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2670 }
2671
2672 TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
2673   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2674
2675   InitWithDtls(false);
2676
2677   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2678   EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
2679   EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
2680 }
2681
2682 TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
2683   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2684   SetFactoryDtlsSrtp();
2685   InitWithDtls(false);
2686
2687   // Create remote offer with SCTP.
2688   cricket::MediaSessionOptions options;
2689   options.data_channel_type = cricket::DCT_SCTP;
2690   JsepSessionDescription* offer =
2691       CreateRemoteOffer(options, cricket::SEC_ENABLED);
2692   SetRemoteDescriptionWithoutError(offer);
2693
2694   // Verifies the answer contains SCTP.
2695   talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2696   EXPECT_TRUE(answer != NULL);
2697   EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
2698   EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
2699 }
2700
2701 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2702   constraints_.reset(new FakeConstraints());
2703   constraints_->AddOptional(
2704       webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
2705   InitWithDtls(false);
2706
2707   SetLocalDescriptionWithDataChannel();
2708   EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2709 }
2710
2711 TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2712   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2713
2714   InitWithDtls(false);
2715
2716   SetLocalDescriptionWithDataChannel();
2717   EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2718 }
2719
2720 TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
2721   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2722   options_.disable_sctp_data_channels = true;
2723   InitWithDtls(false);
2724
2725   SetLocalDescriptionWithDataChannel();
2726   EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2727 }
2728
2729 TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
2730   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2731   const int new_send_port = 9998;
2732   const int new_recv_port = 7775;
2733
2734   InitWithDtls(false);
2735   SetFactoryDtlsSrtp();
2736
2737   // By default, don't actually add the codecs to desc_factory_; they don't
2738   // actually get serialized for SCTP in BuildMediaDescription().  Instead,
2739   // let the session description get parsed.  That'll get the proper codecs
2740   // into the stream.
2741   cricket::MediaSessionOptions options;
2742   JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
2743       "stream1", new_send_port, options);
2744
2745   // SetRemoteDescription will take the ownership of the offer.
2746   SetRemoteDescriptionWithoutError(offer);
2747
2748   SessionDescriptionInterface* answer = ChangeSDPSctpPort(
2749       new_recv_port, CreateAnswer(NULL));
2750   ASSERT_TRUE(answer != NULL);
2751
2752   // Now set the local description, which'll take ownership of the answer.
2753   SetLocalDescriptionWithoutError(answer);
2754
2755   // TEST PLAN: Set the port number to something new, set it in the SDP,
2756   // and pass it all the way down.
2757   webrtc::InternalDataChannelInit dci;
2758   dci.reliable = true;
2759   EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2760   talk_base::scoped_refptr<webrtc::DataChannel> dc =
2761       session_->CreateDataChannel("datachannel", &dci);
2762
2763   cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
2764   int portnum = -1;
2765   ASSERT_TRUE(ch != NULL);
2766   ASSERT_EQ(1UL, ch->send_codecs().size());
2767   EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
2768   EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
2769                       ch->send_codecs()[0].name.c_str()));
2770   EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
2771                                             &portnum));
2772   EXPECT_EQ(new_send_port, portnum);
2773
2774   ASSERT_EQ(1UL, ch->recv_codecs().size());
2775   EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
2776   EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
2777                       ch->recv_codecs()[0].name.c_str()));
2778   EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
2779                                             &portnum));
2780   EXPECT_EQ(new_recv_port, portnum);
2781 }
2782
2783 // Verifies that CreateOffer succeeds when CreateOffer is called before async
2784 // identity generation is finished.
2785 TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
2786   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2787   InitWithDtls(false);
2788
2789   EXPECT_TRUE(session_->waiting_for_identity());
2790   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2791   EXPECT_TRUE(offer != NULL);
2792 }
2793
2794 // Verifies that CreateAnswer succeeds when CreateOffer is called before async
2795 // identity generation is finished.
2796 TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
2797   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2798   InitWithDtls(false);
2799
2800   cricket::MediaSessionOptions options;
2801   scoped_ptr<JsepSessionDescription> offer(
2802         CreateRemoteOffer(options, cricket::SEC_REQUIRED));
2803   ASSERT_TRUE(offer.get() != NULL);
2804   SetRemoteDescriptionWithoutError(offer.release());
2805
2806   talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2807   EXPECT_TRUE(answer != NULL);
2808 }
2809
2810 // Verifies that CreateOffer succeeds when CreateOffer is called after async
2811 // identity generation is finished.
2812 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
2813   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2814   InitWithDtls(false);
2815
2816   EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2817   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2818   EXPECT_TRUE(offer != NULL);
2819 }
2820
2821 // Verifies that CreateOffer fails when CreateOffer is called after async
2822 // identity generation fails.
2823 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
2824   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2825   InitWithDtls(true);
2826
2827   EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2828   talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2829   EXPECT_TRUE(offer == NULL);
2830 }
2831
2832 // Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
2833 // before async identity generation is finished.
2834 TEST_F(WebRtcSessionTest,
2835        TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
2836   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2837   VerifyMultipleAsyncCreateDescription(
2838       true, CreateSessionDescriptionRequest::kOffer);
2839 }
2840
2841 // Verifies that CreateOffer fails when Multiple CreateOffer calls are made
2842 // before async identity generation fails.
2843 TEST_F(WebRtcSessionTest,
2844        TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
2845   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2846   VerifyMultipleAsyncCreateDescription(
2847       false, CreateSessionDescriptionRequest::kOffer);
2848 }
2849
2850 // Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
2851 // before async identity generation is finished.
2852 TEST_F(WebRtcSessionTest,
2853        TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
2854   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2855   VerifyMultipleAsyncCreateDescription(
2856       true, CreateSessionDescriptionRequest::kAnswer);
2857 }
2858
2859 // Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
2860 // before async identity generation fails.
2861 TEST_F(WebRtcSessionTest,
2862        TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
2863   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2864   VerifyMultipleAsyncCreateDescription(
2865       false, CreateSessionDescriptionRequest::kAnswer);
2866 }
2867
2868 // Verifies that setRemoteDescription fails when DTLS is disabled and the remote
2869 // offer has no SDES crypto but only DTLS fingerprint.
2870 TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
2871   // Init without DTLS.
2872   Init(NULL);
2873   // Create a remote offer with secured transport disabled.
2874   cricket::MediaSessionOptions options;
2875   JsepSessionDescription* offer(CreateRemoteOffer(
2876       options, cricket::SEC_DISABLED));
2877   // Adds a DTLS fingerprint to the remote offer.
2878   cricket::SessionDescription* sdp = offer->description();
2879   TransportInfo* audio = sdp->GetTransportInfoByName("audio");
2880   ASSERT_TRUE(audio != NULL);
2881   ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
2882   audio->description.identity_fingerprint.reset(
2883       talk_base::SSLFingerprint::CreateFromRfc4572(
2884           talk_base::DIGEST_SHA_256, kFakeDtlsFingerprint));
2885   SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesAndDtlsDisabled,
2886                                        offer);
2887 }
2888
2889 // This test verifies DSCP is properly applied on the media channels.
2890 TEST_F(WebRtcSessionTest, TestDscpConstraint) {
2891   constraints_.reset(new FakeConstraints());
2892   constraints_->AddOptional(
2893       webrtc::MediaConstraintsInterface::kEnableDscp, true);
2894   Init(NULL);
2895   mediastream_signaling_.SendAudioVideoStream1();
2896   SessionDescriptionInterface* offer = CreateOffer(NULL);
2897
2898   SetLocalDescriptionWithoutError(offer);
2899
2900   video_channel_ = media_engine_->GetVideoChannel(0);
2901   voice_channel_ = media_engine_->GetVoiceChannel(0);
2902
2903   ASSERT_TRUE(video_channel_ != NULL);
2904   ASSERT_TRUE(voice_channel_ != NULL);
2905   cricket::AudioOptions audio_options;
2906   EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
2907   cricket::VideoOptions video_options;
2908   EXPECT_TRUE(video_channel_->GetOptions(&video_options));
2909   EXPECT_TRUE(audio_options.dscp.IsSet());
2910   EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
2911   EXPECT_TRUE(video_options.dscp.IsSet());
2912   EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
2913 }
2914
2915 // TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled.  That test
2916 // currently fails because upon disconnection and reconnection OnIceComplete is
2917 // called more than once without returning to IceGatheringGathering.