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