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