blob: ba76ff399ea06dc05f5f8b56696c7f2bd7eb67b4 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033#include "talk/app/webrtc/test/fakeconstraints.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000034#include "talk/app/webrtc/test/fakedtlsidentityservice.h"
35#include "talk/app/webrtc/test/fakemediastreamsignaling.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000036#include "talk/app/webrtc/videotrack.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/app/webrtc/webrtcsession.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000038#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000039#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"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000043#include "webrtc/p2p/base/stunserver.h"
44#include "webrtc/p2p/base/teststunserver.h"
45#include "webrtc/p2p/base/testturnserver.h"
46#include "webrtc/p2p/client/basicportallocator.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000047#include "talk/session/media/channelmanager.h"
48#include "talk/session/media/mediasession.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000049#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"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060
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;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074using rtc::SocketAddress;
75using rtc::scoped_ptr;
76using rtc::Thread;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000078using webrtc::CreateSessionDescriptionObserver;
79using webrtc::CreateSessionDescriptionRequest;
80using webrtc::DTLSIdentityRequestObserver;
81using webrtc::DTLSIdentityServiceInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082using webrtc::FakeConstraints;
83using webrtc::IceCandidateCollection;
84using webrtc::JsepIceCandidate;
85using webrtc::JsepSessionDescription;
wu@webrtc.org97077a32013-10-25 21:18:33 +000086using webrtc::PeerConnectionFactoryInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::PeerConnectionInterface;
88using webrtc::SessionDescriptionInterface;
89using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000090using webrtc::WebRtcSession;
wu@webrtc.org364f2042013-11-20 21:49:41 +000091using webrtc::kBundleWithoutRtcpMux;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000092using webrtc::kCreateChannelFailed;
93using webrtc::kInvalidSdp;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094using webrtc::kMlineMismatch;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +000095using webrtc::kPushDownTDFailed;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +000096using webrtc::kSdpWithoutIceUfragPwd;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000097using webrtc::kSdpWithoutDtlsFingerprint;
98using webrtc::kSdpWithoutSdesCrypto;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099using webrtc::kSessionError;
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000100using webrtc::kSessionErrorDesc;
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000101using webrtc::kMaxUnsignalledRecvStreams;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000103typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
104
wu@webrtc.org364f2042013-11-20 21:49:41 +0000105static const int kClientAddrPort = 0;
106static const char kClientAddrHost1[] = "11.11.11.11";
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000107static const char kClientIPv6AddrHost1[] =
108 "2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff";
wu@webrtc.org364f2042013-11-20 21:49:41 +0000109static const char kClientAddrHost2[] = "22.22.22.22";
110static const char kStunAddrHost[] = "99.99.99.1";
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000111static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478);
112static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +0000113static const char kTurnUsername[] = "test";
114static const char kTurnPassword[] = "test";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115
116static const char kSessionVersion[] = "1";
117
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118// Media index of candidates belonging to the first media content.
119static const int kMediaContentIndex0 = 0;
120static const char kMediaContentName0[] = "audio";
121
122// Media index of candidates belonging to the second media content.
123static const int kMediaContentIndex1 = 1;
124static const char kMediaContentName1[] = "video";
125
126static const int kIceCandidatesTimeout = 10000;
127
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +0000128static const char kFakeDtlsFingerprint[] =
129 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:"
130 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24";
131
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000132static const char kTooLongIceUfragPwd[] =
133 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
134 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
135 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"
136 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag";
137
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000138// Add some extra |newlines| to the |message| after |line|.
139static void InjectAfter(const std::string& line,
140 const std::string& newlines,
141 std::string* message) {
142 const std::string tmp = line + newlines;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000143 rtc::replace_substrs(line.c_str(), line.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000144 tmp.c_str(), tmp.length(), message);
145}
146
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000147class FakeMetricsObserver : public webrtc::MetricsObserverInterface {
148 public:
149 FakeMetricsObserver() { Reset(); }
150 void Reset() {
151 memset(peer_connection_metrics_counters_, 0,
152 sizeof(peer_connection_metrics_counters_));
153 memset(peer_connection_metrics_name_, 0,
154 sizeof(peer_connection_metrics_name_));
155 }
156
157 virtual void IncrementCounter(
158 webrtc::PeerConnectionMetricsCounter type) OVERRIDE {
159 peer_connection_metrics_counters_[type]++;
160 }
161 virtual void AddHistogramSample(webrtc::PeerConnectionMetricsName type,
162 int value) OVERRIDE {
163 ASSERT(peer_connection_metrics_name_[type] == 0);
164 peer_connection_metrics_name_[type] = value;
165 }
166
167 int peer_connection_metrics_counters_
168 [webrtc::kPeerConnectionMetricsCounter_Max];
169 int peer_connection_metrics_name_[webrtc::kPeerConnectionMetricsCounter_Max];
170
171 virtual int AddRef() OVERRIDE { return 1; }
172 virtual int Release() OVERRIDE { return 1; }
173};
174
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175class MockIceObserver : public webrtc::IceObserver {
176 public:
177 MockIceObserver()
178 : oncandidatesready_(false),
179 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
180 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
181 }
182
183 virtual void OnIceConnectionChange(
184 PeerConnectionInterface::IceConnectionState new_state) {
185 ice_connection_state_ = new_state;
186 }
187 virtual void OnIceGatheringChange(
188 PeerConnectionInterface::IceGatheringState new_state) {
189 // We can never transition back to "new".
190 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
191 ice_gathering_state_ = new_state;
192
193 // oncandidatesready_ really means "ICE gathering is complete".
194 // This if statement ensures that this value remains correct when we
195 // transition from kIceGatheringComplete to kIceGatheringGathering.
196 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
197 oncandidatesready_ = false;
198 }
199 }
200
201 // Found a new candidate.
202 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
wu@webrtc.org364f2042013-11-20 21:49:41 +0000203 switch (candidate->sdp_mline_index()) {
204 case kMediaContentIndex0:
205 mline_0_candidates_.push_back(candidate->candidate());
206 break;
207 case kMediaContentIndex1:
208 mline_1_candidates_.push_back(candidate->candidate());
209 break;
210 default:
211 ASSERT(false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 }
wu@webrtc.org364f2042013-11-20 21:49:41 +0000213
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000214 // The ICE gathering state should always be Gathering when a candidate is
215 // received (or possibly Completed in the case of the final candidate).
216 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
217 }
218
219 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
220 virtual void OnIceComplete() {
221 EXPECT_FALSE(oncandidatesready_);
222 oncandidatesready_ = true;
223
224 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
225 // be called approximately simultaneously. For ease of testing, this
226 // check additionally requires that they be called in the above order.
227 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
228 ice_gathering_state_);
229 }
230
231 bool oncandidatesready_;
232 std::vector<cricket::Candidate> mline_0_candidates_;
233 std::vector<cricket::Candidate> mline_1_candidates_;
234 PeerConnectionInterface::IceConnectionState ice_connection_state_;
235 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
236};
237
238class WebRtcSessionForTest : public webrtc::WebRtcSession {
239 public:
240 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000241 rtc::Thread* signaling_thread,
242 rtc::Thread* worker_thread,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243 cricket::PortAllocator* port_allocator,
244 webrtc::IceObserver* ice_observer,
245 webrtc::MediaStreamSignaling* mediastream_signaling)
246 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
247 mediastream_signaling) {
248 RegisterIceObserver(ice_observer);
249 }
250 virtual ~WebRtcSessionForTest() {}
251
252 using cricket::BaseSession::GetTransportProxy;
253 using webrtc::WebRtcSession::SetAudioPlayout;
254 using webrtc::WebRtcSession::SetAudioSend;
255 using webrtc::WebRtcSession::SetCaptureDevice;
256 using webrtc::WebRtcSession::SetVideoPlayout;
257 using webrtc::WebRtcSession::SetVideoSend;
258};
259
wu@webrtc.org91053e72013-08-10 07:18:04 +0000260class WebRtcSessionCreateSDPObserverForTest
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000261 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000263 enum State {
264 kInit,
265 kFailed,
266 kSucceeded,
267 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000268 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000269
270 // CreateSessionDescriptionObserver implementation.
271 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000272 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000273 state_ = kSucceeded;
274 }
275 virtual void OnFailure(const std::string& error) {
276 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000277 }
278
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000279 SessionDescriptionInterface* description() { return description_.get(); }
280
281 SessionDescriptionInterface* ReleaseDescription() {
282 return description_.release();
283 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284
wu@webrtc.org91053e72013-08-10 07:18:04 +0000285 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286
wu@webrtc.org91053e72013-08-10 07:18:04 +0000287 protected:
288 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289
290 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000291 rtc::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000292 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293};
294
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000295class FakeAudioRenderer : public cricket::AudioRenderer {
296 public:
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000297 FakeAudioRenderer() : channel_id_(-1), sink_(NULL) {}
298 virtual ~FakeAudioRenderer() {
299 if (sink_)
300 sink_->OnClose();
301 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000302
303 virtual void AddChannel(int channel_id) OVERRIDE {
304 ASSERT(channel_id_ == -1);
305 channel_id_ = channel_id;
306 }
307 virtual void RemoveChannel(int channel_id) OVERRIDE {
308 ASSERT(channel_id == channel_id_);
309 channel_id_ = -1;
310 }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000311 virtual void SetSink(Sink* sink) OVERRIDE {
312 sink_ = sink;
313 }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000314
315 int channel_id() const { return channel_id_; }
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000316 cricket::AudioRenderer::Sink* sink() const { return sink_; }
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000317 private:
318 int channel_id_;
henrike@webrtc.orga7b98182014-02-21 15:51:43 +0000319 cricket::AudioRenderer::Sink* sink_;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000320};
321
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322class WebRtcSessionTest : public testing::Test {
323 protected:
324 // TODO Investigate why ChannelManager crashes, if it's created
325 // after stun_server.
326 WebRtcSessionTest()
327 : media_engine_(new cricket::FakeMediaEngine()),
328 data_engine_(new cricket::FakeDataEngine()),
329 device_manager_(new cricket::FakeDeviceManager()),
330 channel_manager_(new cricket::ChannelManager(
331 media_engine_, data_engine_, device_manager_,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000332 new cricket::CaptureManager(), rtc::Thread::Current())),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000333 tdesc_factory_(new cricket::TransportDescriptionFactory()),
334 desc_factory_(new cricket::MediaSessionDescriptionFactory(
335 channel_manager_.get(), tdesc_factory_.get())),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000336 pss_(new rtc::PhysicalSocketServer),
337 vss_(new rtc::VirtualSocketServer(pss_.get())),
338 fss_(new rtc::FirewallSocketServer(vss_.get())),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000339 ss_scope_(fss_.get()),
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000340 stun_socket_addr_(rtc::SocketAddress(kStunAddrHost,
wu@webrtc.org364f2042013-11-20 21:49:41 +0000341 cricket::STUN_SERVER_PORT)),
jiayl@webrtc.orgbebc75e2014-09-26 23:01:11 +0000342 stun_server_(cricket::TestStunServer::Create(Thread::Current(),
343 stun_socket_addr_)),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000344 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000345 mediastream_signaling_(channel_manager_.get()),
346 ice_type_(PeerConnectionInterface::kAll) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000347 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
buildbot@webrtc.org51c55082014-07-28 22:26:15 +0000348
349 cricket::ServerAddresses stun_servers;
350 stun_servers.insert(stun_socket_addr_);
351 allocator_.reset(new cricket::BasicPortAllocator(
352 &network_manager_,
353 stun_servers,
354 SocketAddress(), SocketAddress(), SocketAddress()));
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000355 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 cricket::PORTALLOCATOR_DISABLE_RELAY |
pthatcher@webrtc.org96572652015-01-09 19:08:27 +0000357 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000358 EXPECT_TRUE(channel_manager_->Init());
359 desc_factory_->set_add_legacy_streams(false);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000360 allocator_->set_step_delay(cricket::kMinimumStepDelay);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000361 }
362
363 void AddInterface(const SocketAddress& addr) {
364 network_manager_.AddInterface(addr);
365 }
366
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000367 void SetIceTransportType(PeerConnectionInterface::IceTransportsType type) {
368 ice_type_ = type;
369 }
370
wu@webrtc.org91053e72013-08-10 07:18:04 +0000371 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372 ASSERT_TRUE(session_.get() == NULL);
373 session_.reset(new WebRtcSessionForTest(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000374 channel_manager_.get(), rtc::Thread::Current(),
375 rtc::Thread::Current(), allocator_.get(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000376 &observer_,
377 &mediastream_signaling_));
378
379 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
380 observer_.ice_connection_state_);
381 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
382 observer_.ice_gathering_state_);
383
wu@webrtc.org97077a32013-10-25 21:18:33 +0000384 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(),
buildbot@webrtc.org41451d42014-05-03 05:39:45 +0000385 identity_service, ice_type_));
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000386 session_->set_metrics_observer(&metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 }
388
389 void InitWithDtmfCodec() {
390 // Add kTelephoneEventCodec for dtmf test.
wu@webrtc.org364f2042013-11-20 21:49:41 +0000391 const cricket::AudioCodec kTelephoneEventCodec(
392 106, "telephone-event", 8000, 0, 1, 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000393 std::vector<cricket::AudioCodec> codecs;
394 codecs.push_back(kTelephoneEventCodec);
395 media_engine_->SetAudioCodecs(codecs);
396 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000397 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398 }
399
henrike@webrtc.org7666db72013-08-22 14:45:42 +0000400 void InitWithDtls(bool identity_request_should_fail = false) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000401 FakeIdentityService* identity_service = new FakeIdentityService();
402 identity_service->set_should_fail(identity_request_should_fail);
403 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404 }
405
406 // Creates a local offer and applies it. Starts ice.
407 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
408 // to decide which streams to create.
409 void InitiateCall() {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000410 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 SetLocalDescriptionWithoutError(offer);
412 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
413 observer_.ice_gathering_state_,
414 kIceCandidatesTimeout);
415 }
416
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000417 SessionDescriptionInterface* CreateOffer() {
418 PeerConnectionInterface::RTCOfferAnswerOptions options;
419 options.offer_to_receive_audio =
420 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
421
422 return CreateOffer(options);
423 }
424
wu@webrtc.org91053e72013-08-10 07:18:04 +0000425 SessionDescriptionInterface* CreateOffer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000426 const PeerConnectionInterface::RTCOfferAnswerOptions& options) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000427 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +0000428 observer = new WebRtcSessionCreateSDPObserverForTest();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000429 session_->CreateOffer(observer, options);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000430 EXPECT_TRUE_WAIT(
431 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000432 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000433 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000434 }
435
436 SessionDescriptionInterface* CreateAnswer(
437 const webrtc::MediaConstraintsInterface* constraints) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000438 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
wu@webrtc.org91053e72013-08-10 07:18:04 +0000439 = new WebRtcSessionCreateSDPObserverForTest();
440 session_->CreateAnswer(observer, constraints);
441 EXPECT_TRUE_WAIT(
442 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000443 2000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000444 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000445 }
446
wu@webrtc.org364f2042013-11-20 21:49:41 +0000447 bool ChannelsExist() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000448 return (session_->voice_channel() != NULL &&
449 session_->video_channel() != NULL);
450 }
451
wu@webrtc.org364f2042013-11-20 21:49:41 +0000452 void CheckTransportChannels() const {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
454 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
455 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
456 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
457 }
458
459 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
460 ASSERT_TRUE(session_.get() != NULL);
461 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
462 ASSERT_TRUE(content != NULL);
463 const cricket::AudioContentDescription* audio_content =
464 static_cast<const cricket::AudioContentDescription*>(
465 content->description);
466 ASSERT_TRUE(audio_content != NULL);
467 ASSERT_EQ(1U, audio_content->cryptos().size());
468 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
469 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
470 audio_content->cryptos()[0].cipher_suite);
471 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
472 audio_content->protocol());
473
474 content = cricket::GetFirstVideoContent(sdp);
475 ASSERT_TRUE(content != NULL);
476 const cricket::VideoContentDescription* video_content =
477 static_cast<const cricket::VideoContentDescription*>(
478 content->description);
479 ASSERT_TRUE(video_content != NULL);
480 ASSERT_EQ(1U, video_content->cryptos().size());
481 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
482 video_content->cryptos()[0].cipher_suite);
483 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
484 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
485 video_content->protocol());
486 }
487
488 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
489 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
490 ASSERT_TRUE(content != NULL);
491 const cricket::AudioContentDescription* audio_content =
492 static_cast<const cricket::AudioContentDescription*>(
493 content->description);
494 ASSERT_TRUE(audio_content != NULL);
495 ASSERT_EQ(0U, audio_content->cryptos().size());
496
497 content = cricket::GetFirstVideoContent(sdp);
498 ASSERT_TRUE(content != NULL);
499 const cricket::VideoContentDescription* video_content =
500 static_cast<const cricket::VideoContentDescription*>(
501 content->description);
502 ASSERT_TRUE(video_content != NULL);
503 ASSERT_EQ(0U, video_content->cryptos().size());
504
505 if (dtls) {
506 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
507 audio_content->protocol());
508 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
509 video_content->protocol());
510 } else {
511 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
512 audio_content->protocol());
513 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
514 video_content->protocol());
515 }
516 }
517
518 // Set the internal fake description factories to do DTLS-SRTP.
519 void SetFactoryDtlsSrtp() {
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000520 desc_factory_->set_secure(cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 std::string identity_name = "WebRTC" +
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000522 rtc::ToString(rtc::CreateRandomId());
523 identity_.reset(rtc::SSLIdentity::Generate(identity_name));
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000524 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
526 }
527
528 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
529 bool expected) {
530 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
531 ASSERT_TRUE(audio != NULL);
532 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 const TransportInfo* video = sdp->GetTransportInfoByName("video");
534 ASSERT_TRUE(video != NULL);
535 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 }
537
538 void VerifyAnswerFromNonCryptoOffer() {
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +0000539 // Create an SDP without Crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000540 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000541 options.recv_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000542 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000543 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000544 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 VerifyNoCryptoParams(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000546 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
547 offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000548 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 // Answer should be NULL as no crypto params in offer.
550 ASSERT_TRUE(answer == NULL);
551 }
552
553 void VerifyAnswerFromCryptoOffer() {
554 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000555 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556 options.bundle_enabled = true;
557 scoped_ptr<JsepSessionDescription> offer(
558 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
559 ASSERT_TRUE(offer.get() != NULL);
560 VerifyCryptoParams(offer->description());
561 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000562 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563 ASSERT_TRUE(answer.get() != NULL);
564 VerifyCryptoParams(answer->description());
565 }
566
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +0000567 void SetAndVerifyNumUnsignalledRecvStreams(
568 int value_set, int value_expected) {
569 constraints_.reset(new FakeConstraints());
570 constraints_->AddOptional(
571 webrtc::MediaConstraintsInterface::kNumUnsignalledRecvStreams,
572 value_set);
573 session_.reset();
574 Init(NULL);
575 mediastream_signaling_.SendAudioVideoStream1();
576 SessionDescriptionInterface* offer = CreateOffer();
577
578 SetLocalDescriptionWithoutError(offer);
579
580 video_channel_ = media_engine_->GetVideoChannel(0);
581
582 ASSERT_TRUE(video_channel_ != NULL);
583 cricket::VideoOptions video_options;
584 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
585 EXPECT_EQ(value_expected,
586 video_options.unsignalled_recv_stream_limit.GetWithDefaultIfUnset(-1));
587 }
588
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
590 const cricket::SessionDescription* desc2,
591 bool expect_equal) {
592 if (desc1->contents().size() != desc2->contents().size()) {
593 EXPECT_FALSE(expect_equal);
594 return;
595 }
596
597 const cricket::ContentInfos& contents = desc1->contents();
598 cricket::ContentInfos::const_iterator it = contents.begin();
599
600 for (; it != contents.end(); ++it) {
601 const cricket::TransportDescription* transport_desc1 =
602 desc1->GetTransportDescriptionByName(it->name);
603 const cricket::TransportDescription* transport_desc2 =
604 desc2->GetTransportDescriptionByName(it->name);
605 if (!transport_desc1 || !transport_desc2) {
606 EXPECT_FALSE(expect_equal);
607 return;
608 }
609 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
610 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
611 EXPECT_FALSE(expect_equal);
612 return;
613 }
614 }
615 EXPECT_TRUE(expect_equal);
616 }
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000617
618 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
619 std::string *sdp) {
620 const cricket::SessionDescription* desc = current_desc->description();
621 EXPECT_TRUE(current_desc->ToString(sdp));
622
623 const cricket::ContentInfos& contents = desc->contents();
624 cricket::ContentInfos::const_iterator it = contents.begin();
625 // Replace ufrag and pwd lines with empty strings.
626 for (; it != contents.end(); ++it) {
627 const cricket::TransportDescription* transport_desc =
628 desc->GetTransportDescriptionByName(it->name);
629 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
630 + "\r\n";
631 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
632 + "\r\n";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000633 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000634 "", 0,
635 sdp);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000636 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000637 "", 0,
638 sdp);
639 }
640 }
641
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000642 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc,
643 const std::string& modified_ice_ufrag,
644 const std::string& modified_ice_pwd,
645 std::string* sdp) {
646 const cricket::SessionDescription* desc = current_desc->description();
647 EXPECT_TRUE(current_desc->ToString(sdp));
648
649 const cricket::ContentInfos& contents = desc->contents();
650 cricket::ContentInfos::const_iterator it = contents.begin();
651 // Replace ufrag and pwd lines with |modified_ice_ufrag| and
652 // |modified_ice_pwd| strings.
653 for (; it != contents.end(); ++it) {
654 const cricket::TransportDescription* transport_desc =
655 desc->GetTransportDescriptionByName(it->name);
656 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag
657 + "\r\n";
658 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd
659 + "\r\n";
660 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n";
661 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000662 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(),
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000663 mod_ufrag.c_str(), mod_ufrag.length(),
664 sdp);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000665 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(),
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +0000666 mod_pwd.c_str(), mod_pwd.length(),
667 sdp);
668 }
669 }
670
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000671 // Creates a remote offer and and applies it as a remote description,
672 // creates a local answer and applies is as a local description.
673 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
674 // to decide which local and remote streams to create.
675 void CreateAndSetRemoteOfferAndLocalAnswer() {
676 SessionDescriptionInterface* offer = CreateRemoteOffer();
677 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000678 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 SetLocalDescriptionWithoutError(answer);
680 }
681 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
682 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
683 }
684 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
685 BaseSession::State expected_state) {
686 SetLocalDescriptionWithoutError(desc);
687 EXPECT_EQ(expected_state, session_->state());
688 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000689 void SetLocalDescriptionExpectError(const std::string& action,
690 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 SessionDescriptionInterface* desc) {
692 std::string error;
693 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000694 std::string sdp_type = "local ";
695 sdp_type.append(action);
696 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000697 EXPECT_NE(std::string::npos, error.find(expected_error));
698 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000699 void SetLocalDescriptionOfferExpectError(const std::string& expected_error,
700 SessionDescriptionInterface* desc) {
701 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer,
702 expected_error, desc);
703 }
704 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error,
705 SessionDescriptionInterface* desc) {
706 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer,
707 expected_error, desc);
708 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000709 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
710 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
711 }
712 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
713 BaseSession::State expected_state) {
714 SetRemoteDescriptionWithoutError(desc);
715 EXPECT_EQ(expected_state, session_->state());
716 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000717 void SetRemoteDescriptionExpectError(const std::string& action,
718 const std::string& expected_error,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 SessionDescriptionInterface* desc) {
720 std::string error;
721 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000722 std::string sdp_type = "remote ";
723 sdp_type.append(action);
724 EXPECT_NE(std::string::npos, error.find(sdp_type));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000725 EXPECT_NE(std::string::npos, error.find(expected_error));
726 }
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000727 void SetRemoteDescriptionOfferExpectError(
728 const std::string& expected_error, SessionDescriptionInterface* desc) {
729 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer,
730 expected_error, desc);
731 }
732 void SetRemoteDescriptionPranswerExpectError(
733 const std::string& expected_error, SessionDescriptionInterface* desc) {
734 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer,
735 expected_error, desc);
736 }
737 void SetRemoteDescriptionAnswerExpectError(
738 const std::string& expected_error, SessionDescriptionInterface* desc) {
739 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer,
740 expected_error, desc);
741 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742
743 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
744 SessionDescriptionInterface** nocrypto_answer) {
745 // Create a SDP without Crypto.
746 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000747 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000748 options.bundle_enabled = true;
749 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
750 ASSERT_TRUE(*offer != NULL);
751 VerifyCryptoParams((*offer)->description());
752
753 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
754 cricket::SEC_DISABLED);
755 EXPECT_TRUE(*nocrypto_answer != NULL);
756 }
757
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000758 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
759 SessionDescriptionInterface** nodtls_answer) {
760 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000761 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000762 options.bundle_enabled = true;
763
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000764 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000765 CreateRemoteOffer(options, cricket::SEC_ENABLED));
766
767 *nodtls_answer =
768 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
769 EXPECT_TRUE(*nodtls_answer != NULL);
770 VerifyFingerprintStatus((*nodtls_answer)->description(), false);
771 VerifyCryptoParams((*nodtls_answer)->description());
772
773 SetFactoryDtlsSrtp();
774 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
775 ASSERT_TRUE(*offer != NULL);
776 VerifyFingerprintStatus((*offer)->description(), true);
777 VerifyCryptoParams((*offer)->description());
778 }
779
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000780 JsepSessionDescription* CreateRemoteOfferWithVersion(
781 cricket::MediaSessionOptions options,
782 cricket::SecurePolicy secure_policy,
783 const std::string& session_version,
784 const SessionDescriptionInterface* current_desc) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000785 std::string session_id = rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786 const cricket::SessionDescription* cricket_desc = NULL;
787 if (current_desc) {
788 cricket_desc = current_desc->description();
789 session_id = current_desc->session_id();
790 }
791
792 desc_factory_->set_secure(secure_policy);
793 JsepSessionDescription* offer(
794 new JsepSessionDescription(JsepSessionDescription::kOffer));
795 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
796 session_id, session_version)) {
797 delete offer;
798 offer = NULL;
799 }
800 return offer;
801 }
802 JsepSessionDescription* CreateRemoteOffer(
803 cricket::MediaSessionOptions options) {
804 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
805 kSessionVersion, NULL);
806 }
807 JsepSessionDescription* CreateRemoteOffer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +0000808 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) {
809 return CreateRemoteOfferWithVersion(
810 options, sdes_policy, kSessionVersion, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000811 }
812 JsepSessionDescription* CreateRemoteOffer(
813 cricket::MediaSessionOptions options,
814 const SessionDescriptionInterface* current_desc) {
815 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
816 kSessionVersion, current_desc);
817 }
818
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000819 JsepSessionDescription* CreateRemoteOfferWithSctpPort(
820 const char* sctp_stream_name, int new_port,
821 cricket::MediaSessionOptions options) {
822 options.data_channel_type = cricket::DCT_SCTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000823 options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel",
824 sctp_stream_name);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000825 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
826 }
827
828 // Takes ownership of offer_basis (and deletes it).
829 JsepSessionDescription* ChangeSDPSctpPort(
830 int new_port, webrtc::SessionDescriptionInterface *offer_basis) {
831 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new
832 // SessionDescription from the mutated string.
833 const char* default_port_str = "5000";
834 char new_port_str[16];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000835 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000836 std::string offer_str;
837 offer_basis->ToString(&offer_str);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000838 rtc::replace_substrs(default_port_str, strlen(default_port_str),
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +0000839 new_port_str, strlen(new_port_str),
840 &offer_str);
841 JsepSessionDescription* offer = new JsepSessionDescription(
842 offer_basis->type());
843 delete offer_basis;
844 offer->Initialize(offer_str, NULL);
845 return offer;
846 }
847
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000848 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
849 // before this function to decide which streams to create.
850 JsepSessionDescription* CreateRemoteOffer() {
851 cricket::MediaSessionOptions options;
852 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
853 return CreateRemoteOffer(options, session_->remote_description());
854 }
855
856 JsepSessionDescription* CreateRemoteAnswer(
857 const SessionDescriptionInterface* offer,
858 cricket::MediaSessionOptions options,
859 cricket::SecurePolicy policy) {
860 desc_factory_->set_secure(policy);
861 const std::string session_id =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000862 rtc::ToString(rtc::CreateRandomId64());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000863 JsepSessionDescription* answer(
864 new JsepSessionDescription(JsepSessionDescription::kAnswer));
865 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
866 options, NULL),
867 session_id, kSessionVersion)) {
868 delete answer;
869 answer = NULL;
870 }
871 return answer;
872 }
873
874 JsepSessionDescription* CreateRemoteAnswer(
875 const SessionDescriptionInterface* offer,
876 cricket::MediaSessionOptions options) {
877 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
878 }
879
880 // Creates an answer session description with streams based on
881 // |mediastream_signaling_|. Call
882 // mediastream_signaling_.UseOptionsWithStreamX() before this function
883 // to decide which streams to create.
884 JsepSessionDescription* CreateRemoteAnswer(
885 const SessionDescriptionInterface* offer) {
886 cricket::MediaSessionOptions options;
887 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
888 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
889 }
890
891 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000892 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +0000893 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +0000895
896 PeerConnectionInterface::RTCOfferAnswerOptions options;
897 options.use_rtp_mux = bundle;
898
899 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000900 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
901 // and answer.
902 SetLocalDescriptionWithoutError(offer);
903
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000904 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000905 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 std::string sdp;
907 EXPECT_TRUE(answer->ToString(&sdp));
908
909 size_t expected_candidate_num = 2;
910 if (!rtcp_mux) {
911 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
912 // for rtp and rtcp.
913 expected_candidate_num = 4;
914 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915 const std::string kRtcpMux = "a=rtcp-mux";
916 const std::string kXRtcpMux = "a=xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000917 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 kXRtcpMux.c_str(), kXRtcpMux.length(),
919 &sdp);
920 }
921
922 SessionDescriptionInterface* new_answer = CreateSessionDescription(
923 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000924
925 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000926 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
928 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
929 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
930 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
931 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
932 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
933 if (bundle) {
934 EXPECT_TRUE(c0.IsEquivalent(c1));
935 } else {
936 EXPECT_FALSE(c0.IsEquivalent(c1));
937 }
938 }
939 }
940 // Tests that we can only send DTMF when the dtmf codec is supported.
941 void TestCanInsertDtmf(bool can) {
942 if (can) {
943 InitWithDtmfCodec();
944 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000945 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 }
947 mediastream_signaling_.SendAudioVideoStream1();
948 CreateAndSetRemoteOfferAndLocalAnswer();
949 EXPECT_FALSE(session_->CanInsertDtmf(""));
950 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
951 }
952
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +0000953 // Helper class to configure loopback network and verify Best
954 // Connection using right IP protocol for TestLoopbackCall
955 // method. LoopbackNetworkManager applies firewall rules to block
956 // all ping traffic once ICE completed, and remove them to observe
957 // ICE reconnected again. This LoopbackNetworkConfiguration struct
958 // verifies the best connection is using the right IP protocol after
959 // initial ICE convergences.
960
961 class LoopbackNetworkConfiguration {
962 public:
963 LoopbackNetworkConfiguration()
964 : test_ipv6_network_(false),
965 test_extra_ipv4_network_(false),
966 best_connection_after_initial_ice_converged_(1, 0) {}
967
968 // Used to track the expected best connection count in each IP protocol.
969 struct ExpectedBestConnection {
970 ExpectedBestConnection(int ipv4_count, int ipv6_count)
971 : ipv4_count_(ipv4_count),
972 ipv6_count_(ipv6_count) {}
973
974 int ipv4_count_;
975 int ipv6_count_;
976 };
977
978 bool test_ipv6_network_;
979 bool test_extra_ipv4_network_;
980 ExpectedBestConnection best_connection_after_initial_ice_converged_;
981
982 void VerifyBestConnectionAfterIceConverge(
983 const FakeMetricsObserver& metrics_observer) const {
984 Verify(metrics_observer, best_connection_after_initial_ice_converged_);
985 }
986
987 private:
988 void Verify(const FakeMetricsObserver& metrics_observer,
989 const ExpectedBestConnection& expected) const {
990 EXPECT_EQ(
991 metrics_observer
992 .peer_connection_metrics_counters_[webrtc::kBestConnections_IPv4],
993 expected.ipv4_count_);
994 EXPECT_EQ(
995 metrics_observer
996 .peer_connection_metrics_counters_[webrtc::kBestConnections_IPv6],
997 expected.ipv6_count_);
998 }
999 };
1000
1001 class LoopbackNetworkManager {
1002 public:
1003 LoopbackNetworkManager(WebRtcSessionTest* session,
1004 const LoopbackNetworkConfiguration& config)
1005 : config_(config) {
1006 session->AddInterface(
1007 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1008 if (config_.test_extra_ipv4_network_) {
1009 session->AddInterface(
1010 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1011 }
1012 if (config_.test_ipv6_network_) {
1013 session->AddInterface(
1014 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1015 }
1016 }
1017
1018 void ApplyFirewallRules(rtc::FirewallSocketServer* fss) {
1019 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1020 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1021 if (config_.test_extra_ipv4_network_) {
1022 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1023 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
1024 }
1025 if (config_.test_ipv6_network_) {
1026 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY,
1027 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort));
1028 }
1029 }
1030
1031 void ClearRules(rtc::FirewallSocketServer* fss) { fss->ClearRules(); }
1032
1033 private:
1034 LoopbackNetworkConfiguration config_;
1035 };
1036
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 // The method sets up a call from the session to itself, in a loopback
1038 // arrangement. It also uses a firewall rule to create a temporary
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001039 // disconnection, and then a permanent disconnection.
1040 // This code is placed in a method so that it can be invoked
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001041 // by multiple tests with different allocators (e.g. with and without BUNDLE).
1042 // While running the call, this method also checks if the session goes through
1043 // the correct sequence of ICE states when a connection is established,
1044 // broken, and re-established.
1045 // The Connection state should go:
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001046 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed
1047 // -> Failed.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001048 // The Gathering state should go: New -> Gathering -> Completed.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001049
1050 void TestLoopbackCall(const LoopbackNetworkConfiguration& config) {
1051 LoopbackNetworkManager loopback_network_manager(this, config);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001052 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001053 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001054 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055
1056 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
1057 observer_.ice_gathering_state_);
1058 SetLocalDescriptionWithoutError(offer);
1059 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
1060 observer_.ice_connection_state_);
1061 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
1062 observer_.ice_gathering_state_,
1063 kIceCandidatesTimeout);
1064 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1065 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
1066 observer_.ice_gathering_state_,
1067 kIceCandidatesTimeout);
1068
1069 std::string sdp;
1070 offer->ToString(&sdp);
1071 SessionDescriptionInterface* desc =
1072 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
1073 ASSERT_TRUE(desc != NULL);
1074 SetRemoteDescriptionWithoutError(desc);
1075
1076 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
1077 observer_.ice_connection_state_,
1078 kIceCandidatesTimeout);
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00001079
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001080 // The ice connection state is "Connected" too briefly to catch in a test.
1081 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001082 observer_.ice_connection_state_,
1083 kIceCandidatesTimeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001085 config.VerifyBestConnectionAfterIceConverge(metrics_observer_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001086 // Adding firewall rule to block ping requests, which should cause
1087 // transport channel failure.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001088
1089 loopback_network_manager.ApplyFirewallRules(fss_.get());
1090
1091 LOG(LS_INFO) << "Firewall Rules applied";
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
1093 observer_.ice_connection_state_,
1094 kIceCandidatesTimeout);
1095
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001096 metrics_observer_.Reset();
1097
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001098 // Clearing the rules, session should move back to completed state.
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001099 loopback_network_manager.ClearRules(fss_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001100 // Session is automatically calling OnSignalingReady after creation of
1101 // new portallocator session which will allocate new set of candidates.
1102
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001103 LOG(LS_INFO) << "Firewall Rules cleared";
1104
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001105 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001106 observer_.ice_connection_state_,
1107 kIceCandidatesTimeout);
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001108
1109 // Now we block ping requests and wait until the ICE connection transitions
1110 // to the Failed state. This will take at least 30 seconds because it must
1111 // wait for the Port to timeout.
1112 int port_timeout = 30000;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001113
1114 loopback_network_manager.ApplyFirewallRules(fss_.get());
1115 LOG(LS_INFO) << "Firewall Rules applied again";
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00001116 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionFailed,
1117 observer_.ice_connection_state_,
1118 kIceCandidatesTimeout + port_timeout);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001119 }
1120
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001121 void TestLoopbackCall() {
1122 LoopbackNetworkConfiguration config;
1123 TestLoopbackCall(config);
1124 }
1125
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001126 void VerifyTransportType(const std::string& content_name,
1127 cricket::TransportProtocol protocol) {
1128 const cricket::Transport* transport = session_->GetTransport(content_name);
1129 ASSERT_TRUE(transport != NULL);
1130 EXPECT_EQ(protocol, transport->protocol());
1131 }
1132
1133 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
1134 void AddCNCodecs() {
wu@webrtc.org364f2042013-11-20 21:49:41 +00001135 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
1136 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
1137
1138 // Add kCNCodec for dtmf test.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001139 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
1140 codecs.push_back(kCNCodec1);
1141 codecs.push_back(kCNCodec2);
1142 media_engine_->SetAudioCodecs(codecs);
1143 desc_factory_->set_audio_codecs(codecs);
1144 }
1145
1146 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
1147 const cricket::ContentDescription* description = content->description;
1148 ASSERT(description != NULL);
1149 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001150 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 ASSERT(audio_content_desc != NULL);
1152 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
1153 if (audio_content_desc->codecs()[i].name == "CN")
1154 return false;
1155 }
1156 return true;
1157 }
1158
1159 void SetLocalDescriptionWithDataChannel() {
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00001160 webrtc::InternalDataChannelInit dci;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 dci.reliable = false;
1162 session_->CreateDataChannel("datachannel", &dci);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001163 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 SetLocalDescriptionWithoutError(offer);
1165 }
1166
wu@webrtc.org91053e72013-08-10 07:18:04 +00001167 void VerifyMultipleAsyncCreateDescription(
1168 bool success, CreateSessionDescriptionRequest::Type type) {
henrike@webrtc.org7666db72013-08-22 14:45:42 +00001169 InitWithDtls(!success);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001170 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001171 if (type == CreateSessionDescriptionRequest::kAnswer) {
1172 cricket::MediaSessionOptions options;
1173 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001174 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001175 ASSERT_TRUE(offer.get() != NULL);
1176 SetRemoteDescriptionWithoutError(offer.release());
1177 }
1178
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001179 PeerConnectionInterface::RTCOfferAnswerOptions options;
wu@webrtc.org91053e72013-08-10 07:18:04 +00001180 const int kNumber = 3;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001181 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
wu@webrtc.org91053e72013-08-10 07:18:04 +00001182 observers[kNumber];
1183 for (int i = 0; i < kNumber; ++i) {
1184 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
1185 if (type == CreateSessionDescriptionRequest::kOffer) {
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001186 session_->CreateOffer(observers[i], options);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001187 } else {
1188 session_->CreateAnswer(observers[i], NULL);
1189 }
1190 }
1191
1192 WebRtcSessionCreateSDPObserverForTest::State expected_state =
1193 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
1194 WebRtcSessionCreateSDPObserverForTest::kFailed;
1195
1196 for (int i = 0; i < kNumber; ++i) {
1197 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
1198 if (success) {
1199 EXPECT_TRUE(observers[i]->description() != NULL);
1200 } else {
1201 EXPECT_TRUE(observers[i]->description() == NULL);
1202 }
1203 }
1204 }
1205
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001206 void ConfigureAllocatorWithTurn() {
1207 cricket::RelayServerConfig relay_server(cricket::RELAY_TURN);
1208 cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword);
1209 relay_server.credentials = credentials;
1210 relay_server.ports.push_back(cricket::ProtocolAddress(
1211 kTurnUdpIntAddr, cricket::PROTO_UDP, false));
1212 allocator_->AddRelay(relay_server);
1213 allocator_->set_step_delay(cricket::kMinimumStepDelay);
1214 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
pthatcher@webrtc.org96572652015-01-09 19:08:27 +00001215 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001216 }
1217
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218 cricket::FakeMediaEngine* media_engine_;
1219 cricket::FakeDataEngine* data_engine_;
1220 cricket::FakeDeviceManager* device_manager_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001221 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_;
1222 rtc::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
1223 rtc::scoped_ptr<rtc::SSLIdentity> identity_;
1224 rtc::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
1225 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
1226 rtc::scoped_ptr<rtc::VirtualSocketServer> vss_;
1227 rtc::scoped_ptr<rtc::FirewallSocketServer> fss_;
1228 rtc::SocketServerScope ss_scope_;
1229 rtc::SocketAddress stun_socket_addr_;
jiayl@webrtc.orgbebc75e2014-09-26 23:01:11 +00001230 rtc::scoped_ptr<cricket::TestStunServer> stun_server_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001231 cricket::TestTurnServer turn_server_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001232 rtc::FakeNetworkManager network_manager_;
1233 rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_;
wu@webrtc.org97077a32013-10-25 21:18:33 +00001234 PeerConnectionFactoryInterface::Options options_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001235 rtc::scoped_ptr<FakeConstraints> constraints_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001236 FakeMediaStreamSignaling mediastream_signaling_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001237 rtc::scoped_ptr<WebRtcSessionForTest> session_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001238 MockIceObserver observer_;
1239 cricket::FakeVideoMediaChannel* video_channel_;
1240 cricket::FakeVoiceMediaChannel* voice_channel_;
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00001241 PeerConnectionInterface::IceTransportsType ice_type_;
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00001242 FakeMetricsObserver metrics_observer_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001243};
1244
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
1246 InitWithDtls();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001247 // SDES is disabled when DTLS is on.
1248 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001249}
1250
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001251TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001252 Init(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001253 // SDES is required if DTLS is off.
1254 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001255}
1256
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257TEST_F(WebRtcSessionTest, TestSessionCandidates) {
1258 TestSessionCandidatesWithBundleRtcpMux(false, false);
1259}
1260
1261// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
1262// with rtcp-mux and/or bundle.
1263TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
1264 TestSessionCandidatesWithBundleRtcpMux(false, true);
1265}
1266
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001267TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
1268 TestSessionCandidatesWithBundleRtcpMux(true, true);
1269}
1270
1271TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001272 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1273 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001274 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001275 mediastream_signaling_.SendAudioVideoStream1();
1276 InitiateCall();
1277 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1278 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
1279 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
1280}
1281
1282TEST_F(WebRtcSessionTest, TestStunError) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001283 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1284 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort));
wu@webrtc.org364f2042013-11-20 21:49:41 +00001285 fss_->AddRule(false,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001286 rtc::FP_UDP,
1287 rtc::FD_ANY,
1288 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001289 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 mediastream_signaling_.SendAudioVideoStream1();
1291 InitiateCall();
wu@webrtc.org364f2042013-11-20 21:49:41 +00001292 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001293 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1294 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
1295 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
1296}
1297
mallinath@webrtc.org3d81b1b2014-09-09 14:38:10 +00001298// Test session delivers no candidates gathered when constraint set to "none".
1299TEST_F(WebRtcSessionTest, TestIceTransportsNone) {
1300 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1301 SetIceTransportType(PeerConnectionInterface::kNone);
1302 Init(NULL);
1303 mediastream_signaling_.SendAudioVideoStream1();
1304 InitiateCall();
1305 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1306 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1307 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1308}
1309
1310// Test session delivers only relay candidates gathered when constaint set to
1311// "relay".
1312TEST_F(WebRtcSessionTest, TestIceTransportsRelay) {
1313 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1314 ConfigureAllocatorWithTurn();
1315 SetIceTransportType(PeerConnectionInterface::kRelay);
1316 Init(NULL);
1317 mediastream_signaling_.SendAudioVideoStream1();
1318 InitiateCall();
1319 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1320 EXPECT_EQ(2u, observer_.mline_0_candidates_.size());
1321 EXPECT_EQ(2u, observer_.mline_1_candidates_.size());
1322 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
1323 EXPECT_EQ(cricket::RELAY_PORT_TYPE,
1324 observer_.mline_0_candidates_[i].type());
1325 }
1326 for (size_t i = 0; i < observer_.mline_1_candidates_.size(); ++i) {
1327 EXPECT_EQ(cricket::RELAY_PORT_TYPE,
1328 observer_.mline_1_candidates_[i].type());
1329 }
1330}
1331
1332// Test session delivers all candidates gathered when constaint set to "all".
1333TEST_F(WebRtcSessionTest, TestIceTransportsAll) {
1334 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
1335 SetIceTransportType(PeerConnectionInterface::kAll);
1336 Init(NULL);
1337 mediastream_signaling_.SendAudioVideoStream1();
1338 InitiateCall();
1339 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1340 // Host + STUN. By default allocator is disabled to gather relay candidates.
1341 EXPECT_EQ(4u, observer_.mline_0_candidates_.size());
1342 EXPECT_EQ(4u, observer_.mline_1_candidates_.size());
1343}
1344
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001345TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) {
1346 Init(NULL);
1347 SessionDescriptionInterface* offer = NULL;
1348 // Since |offer| is NULL, there's no way to tell if it's an offer or answer.
1349 std::string unknown_action;
1350 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1351 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer);
1352}
1353
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001354// Test creating offers and receive answers and make sure the
1355// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001356TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001357 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001358 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001359 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 const std::string session_id_orig = offer->session_id();
1361 const std::string session_version_orig = offer->session_version();
1362 SetLocalDescriptionWithoutError(offer);
1363
1364 mediastream_signaling_.SendAudioVideoStream2();
1365 SessionDescriptionInterface* answer =
1366 CreateRemoteAnswer(session_->local_description());
1367 SetRemoteDescriptionWithoutError(answer);
1368
1369 video_channel_ = media_engine_->GetVideoChannel(0);
1370 voice_channel_ = media_engine_->GetVoiceChannel(0);
1371
1372 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1373 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1374
1375 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1376 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1377
1378 ASSERT_EQ(1u, video_channel_->send_streams().size());
1379 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1380 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1381 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1382
1383 // Create new offer without send streams.
1384 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001385 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001386
1387 // Verify the session id is the same and the session version is
1388 // increased.
1389 EXPECT_EQ(session_id_orig, offer->session_id());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001390 EXPECT_LT(rtc::FromString<uint64>(session_version_orig),
1391 rtc::FromString<uint64>(offer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392
1393 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00001394 EXPECT_EQ(0u, video_channel_->send_streams().size());
1395 EXPECT_EQ(0u, voice_channel_->send_streams().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396
1397 mediastream_signaling_.SendAudioVideoStream2();
1398 answer = CreateRemoteAnswer(session_->local_description());
1399 SetRemoteDescriptionWithoutError(answer);
1400
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001401 // Make sure the receive streams have not changed.
1402 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1403 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1404 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1405 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1406}
1407
1408// Test receiving offers and creating answers and make sure the
1409// media engine creates the expected send and receive streams.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001410TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001411 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001412 mediastream_signaling_.SendAudioVideoStream2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001413 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001414 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001415 SetRemoteDescriptionWithoutError(offer);
1416
1417 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001418 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001419 VerifyCryptoParams(answer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001420 SetLocalDescriptionWithoutError(answer);
1421
1422 const std::string session_id_orig = answer->session_id();
1423 const std::string session_version_orig = answer->session_version();
1424
1425 video_channel_ = media_engine_->GetVideoChannel(0);
1426 voice_channel_ = media_engine_->GetVoiceChannel(0);
1427
1428 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1429 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1430
1431 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1432 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1433
1434 ASSERT_EQ(1u, video_channel_->send_streams().size());
1435 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1436 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1437 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1438
1439 mediastream_signaling_.SendAudioVideoStream1And2();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001440 offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001441 SetRemoteDescriptionWithoutError(offer);
1442
1443 // Answer by turning off all send streams.
1444 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001445 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001446
1447 // Verify the session id is the same and the session version is
1448 // increased.
1449 EXPECT_EQ(session_id_orig, answer->session_id());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001450 EXPECT_LT(rtc::FromString<uint64>(session_version_orig),
1451 rtc::FromString<uint64>(answer->session_version()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 SetLocalDescriptionWithoutError(answer);
1453
1454 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1455 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1456 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1457 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1458 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1459 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1460
1461 // Make sure we have no send streams.
1462 EXPECT_EQ(0u, video_channel_->send_streams().size());
1463 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1464}
1465
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001466TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) {
1467 Init(NULL);
1468 media_engine_->set_fail_create_channel(true);
1469
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001470 SessionDescriptionInterface* offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001471 ASSERT_TRUE(offer != NULL);
1472 // SetRemoteDescription and SetLocalDescription will take the ownership of
1473 // the offer.
1474 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001475 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001476 ASSERT_TRUE(offer != NULL);
1477 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer);
1478}
1479
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001480//
1481// Tests for creating/setting SDP under different SDES/DTLS polices:
1482//
1483// --DTLS off and SDES on
1484// TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer:
1485// set local/remote offer/answer with crypto --> success
1486// TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto --->
1487// failure
1488// TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto -->
1489// failure
1490// TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto -->
1491// failure
1492//
1493// --DTLS on and SDES off
1494// TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer:
1495// set local/remote offer/answer with DTLS fingerprint --> success
1496// TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS
1497// fingerprint --> failure
1498// TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint
1499// --> failure
1500// TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint
1501// --> failure
1502//
1503// --Encryption disabled: DTLS off and SDES off
1504// TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote
1505// answer without SDES or DTLS --> success
1506// TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local
1507// answer without SDES or DTLS --> success
1508//
1509
1510// Test that we return a failure when applying a remote/local offer that doesn't
1511// have cryptos enabled when DTLS is off.
1512TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001513 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001515 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001516 JsepSessionDescription* offer = CreateRemoteOffer(
1517 options, cricket::SEC_DISABLED);
1518 ASSERT_TRUE(offer != NULL);
1519 VerifyNoCryptoParams(offer->description(), false);
1520 // SetRemoteDescription and SetLocalDescription will take the ownership of
1521 // the offer.
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001522 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001523 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1524 ASSERT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001525 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526}
1527
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001528// Test that we return a failure when applying a local answer that doesn't have
1529// cryptos enabled when DTLS is off.
1530TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001531 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 SessionDescriptionInterface* offer = NULL;
1533 SessionDescriptionInterface* answer = NULL;
1534 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1535 // SetRemoteDescription and SetLocalDescription will take the ownership of
1536 // the offer.
1537 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001538 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539}
1540
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001541// Test we will return fail when apply an remote answer that doesn't have
1542// crypto enabled when DTLS is off.
1543TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001544 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 SessionDescriptionInterface* offer = NULL;
1546 SessionDescriptionInterface* answer = NULL;
1547 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1548 // SetRemoteDescription and SetLocalDescription will take the ownership of
1549 // the offer.
1550 SetLocalDescriptionWithoutError(offer);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001551 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552}
1553
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001554// Test that we accept an offer with a DTLS fingerprint when DTLS is on
1555// and that we return an answer with a DTLS fingerprint.
1556TEST_F(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001557 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 mediastream_signaling_.SendAudioVideoStream1();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 InitWithDtls();
1560 SetFactoryDtlsSrtp();
1561 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001562 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001563 JsepSessionDescription* offer =
1564 CreateRemoteOffer(options, cricket::SEC_DISABLED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001565 ASSERT_TRUE(offer != NULL);
1566 VerifyFingerprintStatus(offer->description(), true);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001567 VerifyNoCryptoParams(offer->description(), true);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001568
1569 // SetRemoteDescription will take the ownership of the offer.
1570 SetRemoteDescriptionWithoutError(offer);
1571
1572 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001573 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 ASSERT_TRUE(answer != NULL);
1575 VerifyFingerprintStatus(answer->description(), true);
1576 // Check that we don't have an a=crypto line in the answer.
1577 VerifyNoCryptoParams(answer->description(), true);
1578
1579 // Now set the local description, which should work, even without a=crypto.
1580 SetLocalDescriptionWithoutError(answer);
1581}
1582
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001583// Test that we set a local offer with a DTLS fingerprint when DTLS is on
1584// and then we accept a remote answer with a DTLS fingerprint successfully.
1585TEST_F(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001586 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001587 mediastream_signaling_.SendAudioVideoStream1();
1588 InitWithDtls();
1589 SetFactoryDtlsSrtp();
1590
1591 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001592 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001593 ASSERT_TRUE(offer != NULL);
1594 VerifyFingerprintStatus(offer->description(), true);
1595 // Check that we don't have an a=crypto line in the offer.
1596 VerifyNoCryptoParams(offer->description(), true);
1597
1598 // Now set the local description, which should work, even without a=crypto.
1599 SetLocalDescriptionWithoutError(offer);
1600
1601 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001602 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001603 JsepSessionDescription* answer =
1604 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1605 ASSERT_TRUE(answer != NULL);
1606 VerifyFingerprintStatus(answer->description(), true);
1607 VerifyNoCryptoParams(answer->description(), true);
1608
1609 // SetRemoteDescription will take the ownership of the answer.
1610 SetRemoteDescriptionWithoutError(answer);
1611}
1612
1613// Test that if we support DTLS and the other side didn't offer a fingerprint,
1614// we will fail to set the remote description.
1615TEST_F(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001616 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 InitWithDtls();
1618 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001619 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001620 options.bundle_enabled = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621 JsepSessionDescription* offer = CreateRemoteOffer(
1622 options, cricket::SEC_REQUIRED);
1623 ASSERT_TRUE(offer != NULL);
1624 VerifyFingerprintStatus(offer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001625 VerifyCryptoParams(offer->description());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001627 // SetRemoteDescription will take the ownership of the offer.
1628 SetRemoteDescriptionOfferExpectError(
1629 kSdpWithoutDtlsFingerprint, offer);
1630
1631 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED);
1632 // SetLocalDescription will take the ownership of the offer.
1633 SetLocalDescriptionOfferExpectError(
1634 kSdpWithoutDtlsFingerprint, offer);
1635}
1636
1637// Test that we return a failure when applying a local answer that doesn't have
1638// a DTLS fingerprint when DTLS is required.
1639TEST_F(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001640 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001641 InitWithDtls();
1642 SessionDescriptionInterface* offer = NULL;
1643 SessionDescriptionInterface* answer = NULL;
1644 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer);
1645
1646 // SetRemoteDescription and SetLocalDescription will take the ownership of
1647 // the offer and answer.
1648 SetRemoteDescriptionWithoutError(offer);
1649 SetLocalDescriptionAnswerExpectError(
1650 kSdpWithoutDtlsFingerprint, answer);
1651}
1652
1653// Test that we return a failure when applying a remote answer that doesn't have
1654// a DTLS fingerprint when DTLS is required.
1655TEST_F(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001656 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001657 InitWithDtls();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001658 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001659 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001660 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001661 JsepSessionDescription* answer =
1662 CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
1663
1664 // SetRemoteDescription and SetLocalDescription will take the ownership of
1665 // the offer and answer.
1666 SetLocalDescriptionWithoutError(offer);
1667 SetRemoteDescriptionAnswerExpectError(
1668 kSdpWithoutDtlsFingerprint, answer);
1669}
1670
1671// Test that we create a local offer without SDES or DTLS and accept a remote
1672// answer without SDES or DTLS when encryption is disabled.
1673TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) {
1674 mediastream_signaling_.SendAudioVideoStream1();
1675 options_.disable_encryption = true;
1676 InitWithDtls();
1677
1678 // Verify that we get a crypto fingerprint in the answer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001679 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001680 ASSERT_TRUE(offer != NULL);
1681 VerifyFingerprintStatus(offer->description(), false);
1682 // Check that we don't have an a=crypto line in the offer.
1683 VerifyNoCryptoParams(offer->description(), false);
1684
1685 // Now set the local description, which should work, even without a=crypto.
1686 SetLocalDescriptionWithoutError(offer);
1687
1688 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001689 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001690 JsepSessionDescription* answer =
1691 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
1692 ASSERT_TRUE(answer != NULL);
1693 VerifyFingerprintStatus(answer->description(), false);
1694 VerifyNoCryptoParams(answer->description(), false);
1695
1696 // SetRemoteDescription will take the ownership of the answer.
1697 SetRemoteDescriptionWithoutError(answer);
1698}
1699
1700// Test that we create a local answer without SDES or DTLS and accept a remote
1701// offer without SDES or DTLS when encryption is disabled.
1702TEST_F(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) {
1703 options_.disable_encryption = true;
1704 InitWithDtls();
1705
1706 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001707 options.recv_video = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001708 JsepSessionDescription* offer =
1709 CreateRemoteOffer(options, cricket::SEC_DISABLED);
1710 ASSERT_TRUE(offer != NULL);
1711 VerifyFingerprintStatus(offer->description(), false);
1712 VerifyNoCryptoParams(offer->description(), false);
1713
1714 // SetRemoteDescription will take the ownership of the offer.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715 SetRemoteDescriptionWithoutError(offer);
1716
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001717 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001718 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001719 ASSERT_TRUE(answer != NULL);
1720 VerifyFingerprintStatus(answer->description(), false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001721 // Check that we don't have an a=crypto line in the answer.
1722 VerifyNoCryptoParams(answer->description(), false);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001723
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00001724 // Now set the local description, which should work, even without a=crypto.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001725 SetLocalDescriptionWithoutError(answer);
1726}
1727
1728TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001729 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730 mediastream_signaling_.SendNothing();
1731 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001732 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733 SetLocalDescriptionWithoutError(offer);
1734
1735 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001736 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737 SetLocalDescriptionWithoutError(offer2);
1738}
1739
1740TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001741 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001742 mediastream_signaling_.SendNothing();
1743 // SetLocalDescription take ownership of offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001744 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001745 SetRemoteDescriptionWithoutError(offer);
1746
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001747 SessionDescriptionInterface* offer2 = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001748 SetRemoteDescriptionWithoutError(offer2);
1749}
1750
1751TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001752 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001753 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001754 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001755 SetLocalDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001756 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001757 SetRemoteDescriptionOfferExpectError(
1758 "Called in wrong state: STATE_SENTINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759}
1760
1761TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001762 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001763 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001764 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001765 SetRemoteDescriptionWithoutError(offer);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001766 offer = CreateOffer();
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001767 SetLocalDescriptionOfferExpectError(
1768 "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769}
1770
1771TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001772 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773 mediastream_signaling_.SendNothing();
1774 SessionDescriptionInterface* offer = CreateRemoteOffer();
1775 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1776
1777 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001778 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001779 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1780 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1781
1782 mediastream_signaling_.SendAudioVideoStream1();
1783 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001784 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1786
1787 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1788
1789 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001790 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001791 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1792}
1793
1794TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001795 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001797 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1799
1800 JsepSessionDescription* pranswer =
1801 CreateRemoteAnswer(session_->local_description());
1802 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1803
1804 SetRemoteDescriptionExpectState(pranswer,
1805 BaseSession::STATE_RECEIVEDPRACCEPT);
1806
1807 mediastream_signaling_.SendAudioVideoStream1();
1808 JsepSessionDescription* pranswer2 =
1809 CreateRemoteAnswer(session_->local_description());
1810 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1811
1812 SetRemoteDescriptionExpectState(pranswer2,
1813 BaseSession::STATE_RECEIVEDPRACCEPT);
1814
1815 mediastream_signaling_.SendAudioVideoStream2();
1816 SessionDescriptionInterface* answer =
1817 CreateRemoteAnswer(session_->local_description());
1818 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1819}
1820
1821TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001822 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001824 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
1825
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001826 SessionDescriptionInterface* answer =
1827 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001828 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT",
1829 answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001830}
1831
1832TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001833 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001834 mediastream_signaling_.SendNothing();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001835 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
1836
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001837 SessionDescriptionInterface* answer =
1838 CreateRemoteAnswer(offer.get());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00001839 SetRemoteDescriptionAnswerExpectError(
1840 "Called in wrong state: STATE_INIT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841}
1842
1843TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001844 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001845 mediastream_signaling_.SendAudioVideoStream1();
1846
1847 cricket::Candidate candidate;
1848 candidate.set_component(1);
1849 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1850
1851 // Fail since we have not set a offer description.
1852 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1853
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001854 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855 SetLocalDescriptionWithoutError(offer);
1856 // Candidate should be allowed to add before remote description.
1857 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1858 candidate.set_component(2);
1859 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1860 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1861
1862 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1863 session_->local_description());
1864 SetRemoteDescriptionWithoutError(answer);
1865
1866 // Verifying the candidates are copied properly from internal vector.
1867 const SessionDescriptionInterface* remote_desc =
1868 session_->remote_description();
1869 ASSERT_TRUE(remote_desc != NULL);
1870 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1871 const IceCandidateCollection* candidates =
1872 remote_desc->candidates(kMediaContentIndex0);
1873 ASSERT_EQ(2u, candidates->count());
1874 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1875 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1876 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1877 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1878
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001879 // |ice_candidate3| is identical to |ice_candidate2|. It can be added
1880 // successfully, but the total count of candidates will not increase.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881 candidate.set_component(2);
1882 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1883 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
mallinath@webrtc.org67ee6b92014-02-03 16:57:16 +00001884 ASSERT_EQ(2u, candidates->count());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001885
1886 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1887 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1888}
1889
1890// Test that a remote candidate is added to the remote session description and
1891// that it is retained if the remote session description is changed.
1892TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001893 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001894 cricket::Candidate candidate1;
1895 candidate1.set_component(1);
1896 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1897 candidate1);
1898 mediastream_signaling_.SendAudioVideoStream1();
1899 CreateAndSetRemoteOfferAndLocalAnswer();
1900
1901 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1902 const SessionDescriptionInterface* remote_desc =
1903 session_->remote_description();
1904 ASSERT_TRUE(remote_desc != NULL);
1905 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1906 const IceCandidateCollection* candidates =
1907 remote_desc->candidates(kMediaContentIndex0);
1908 ASSERT_EQ(1u, candidates->count());
1909 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1910
1911 // Update the RemoteSessionDescription with a new session description and
1912 // a candidate and check that the new remote session description contains both
1913 // candidates.
1914 SessionDescriptionInterface* offer = CreateRemoteOffer();
1915 cricket::Candidate candidate2;
1916 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1917 candidate2);
1918 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1919 SetRemoteDescriptionWithoutError(offer);
1920
1921 remote_desc = session_->remote_description();
1922 ASSERT_TRUE(remote_desc != NULL);
1923 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1924 candidates = remote_desc->candidates(kMediaContentIndex0);
1925 ASSERT_EQ(2u, candidates->count());
1926 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1927 // Username and password have be updated with the TransportInfo of the
1928 // SessionDescription, won't be equal to the original one.
1929 candidate2.set_username(candidates->at(0)->candidate().username());
1930 candidate2.set_password(candidates->at(0)->candidate().password());
1931 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1932 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1933 // No need to verify the username and password.
1934 candidate1.set_username(candidates->at(1)->candidate().username());
1935 candidate1.set_password(candidates->at(1)->candidate().password());
1936 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1937
1938 // Test that the candidate is ignored if we can add the same candidate again.
1939 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1940}
1941
1942// Test that local candidates are added to the local session description and
1943// that they are retained if the local session description is changed.
1944TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001945 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00001946 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001947 mediastream_signaling_.SendAudioVideoStream1();
1948 CreateAndSetRemoteOfferAndLocalAnswer();
1949
1950 const SessionDescriptionInterface* local_desc = session_->local_description();
1951 const IceCandidateCollection* candidates =
1952 local_desc->candidates(kMediaContentIndex0);
1953 ASSERT_TRUE(candidates != NULL);
1954 EXPECT_EQ(0u, candidates->count());
1955
1956 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1957
1958 local_desc = session_->local_description();
1959 candidates = local_desc->candidates(kMediaContentIndex0);
1960 ASSERT_TRUE(candidates != NULL);
1961 EXPECT_LT(0u, candidates->count());
1962 candidates = local_desc->candidates(1);
1963 ASSERT_TRUE(candidates != NULL);
1964 EXPECT_LT(0u, candidates->count());
1965
1966 // Update the session descriptions.
1967 mediastream_signaling_.SendAudioVideoStream1();
1968 CreateAndSetRemoteOfferAndLocalAnswer();
1969
1970 local_desc = session_->local_description();
1971 candidates = local_desc->candidates(kMediaContentIndex0);
1972 ASSERT_TRUE(candidates != NULL);
1973 EXPECT_LT(0u, candidates->count());
1974 candidates = local_desc->candidates(1);
1975 ASSERT_TRUE(candidates != NULL);
1976 EXPECT_LT(0u, candidates->count());
1977}
1978
1979// Test that we can set a remote session description with remote candidates.
1980TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001981 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982
1983 cricket::Candidate candidate1;
1984 candidate1.set_component(1);
1985 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1986 candidate1);
1987 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00001988 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989
1990 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1991 SetRemoteDescriptionWithoutError(offer);
1992
1993 const SessionDescriptionInterface* remote_desc =
1994 session_->remote_description();
1995 ASSERT_TRUE(remote_desc != NULL);
1996 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1997 const IceCandidateCollection* candidates =
1998 remote_desc->candidates(kMediaContentIndex0);
1999 ASSERT_EQ(1u, candidates->count());
2000 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
2001
wu@webrtc.org91053e72013-08-10 07:18:04 +00002002 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 SetLocalDescriptionWithoutError(answer);
2004}
2005
2006// Test that offers and answers contains ice candidates when Ice candidates have
2007// been gathered.
2008TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002009 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
wu@webrtc.org91053e72013-08-10 07:18:04 +00002010 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011 mediastream_signaling_.SendAudioVideoStream1();
2012 // Ice is started but candidates are not provided until SetLocalDescription
2013 // is called.
2014 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
2015 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
2016 CreateAndSetRemoteOfferAndLocalAnswer();
2017 // Wait until at least one local candidate has been collected.
2018 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
2019 kIceCandidatesTimeout);
2020 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
2021 kIceCandidatesTimeout);
2022
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002023 rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
2024
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
2026 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
2027 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
2028 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
2029
2030 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
2031 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002032 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
2034 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
2035 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
2036 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
2037 SetLocalDescriptionWithoutError(answer);
2038}
2039
2040// Verifies TransportProxy and media channels are created with content names
2041// present in the SessionDescription.
2042TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002043 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002044 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002045 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046
2047 // CreateOffer creates session description with the content names "audio" and
2048 // "video". Goal is to modify these content names and verify transport channel
2049 // proxy in the BaseSession, as proxies are created with the content names
2050 // present in SDP.
2051 std::string sdp;
2052 EXPECT_TRUE(offer->ToString(&sdp));
2053 const std::string kAudioMid = "a=mid:audio";
2054 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2055 const std::string kVideoMid = "a=mid:video";
2056 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
2057
2058 // Replacing |audio| with |audio_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002059 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 kAudioMidReplaceStr.c_str(),
2061 kAudioMidReplaceStr.length(),
2062 &sdp);
2063 // Replacing |video| with |video_content_name|.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002064 rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 kVideoMidReplaceStr.c_str(),
2066 kVideoMidReplaceStr.length(),
2067 &sdp);
2068
2069 SessionDescriptionInterface* modified_offer =
2070 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2071
2072 SetRemoteDescriptionWithoutError(modified_offer);
2073
2074 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00002075 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002076 SetLocalDescriptionWithoutError(answer);
2077
2078 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
2079 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
2080 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
2081 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
2082}
2083
2084// Test that an offer contains the correct media content descriptions based on
2085// the send streams when no constraints have been set.
2086TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002087 Init(NULL);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002088 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2089
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002090 ASSERT_TRUE(offer != NULL);
2091 const cricket::ContentInfo* content =
2092 cricket::GetFirstAudioContent(offer->description());
2093 EXPECT_TRUE(content != NULL);
2094 content = cricket::GetFirstVideoContent(offer->description());
2095 EXPECT_TRUE(content == NULL);
2096}
2097
2098// Test that an offer contains the correct media content descriptions based on
2099// the send streams when no constraints have been set.
2100TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002101 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002102 // Test Audio only offer.
2103 mediastream_signaling_.UseOptionsAudioOnly();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002104 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2105
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002106 const cricket::ContentInfo* content =
2107 cricket::GetFirstAudioContent(offer->description());
2108 EXPECT_TRUE(content != NULL);
2109 content = cricket::GetFirstVideoContent(offer->description());
2110 EXPECT_TRUE(content == NULL);
2111
2112 // Test Audio / Video offer.
2113 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002114 offer.reset(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 content = cricket::GetFirstAudioContent(offer->description());
2116 EXPECT_TRUE(content != NULL);
2117 content = cricket::GetFirstVideoContent(offer->description());
2118 EXPECT_TRUE(content != NULL);
2119}
2120
2121// Test that an offer contains no media content descriptions if
2122// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
2123TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002124 Init(NULL);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002125 PeerConnectionInterface::RTCOfferAnswerOptions options;
2126 options.offer_to_receive_audio = 0;
2127 options.offer_to_receive_video = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002128
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002129 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002130 CreateOffer(options));
2131
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002132 ASSERT_TRUE(offer != NULL);
2133 const cricket::ContentInfo* content =
2134 cricket::GetFirstAudioContent(offer->description());
2135 EXPECT_TRUE(content == NULL);
2136 content = cricket::GetFirstVideoContent(offer->description());
2137 EXPECT_TRUE(content == NULL);
2138}
2139
2140// Test that an offer contains only audio media content descriptions if
2141// kOfferToReceiveAudio constraints are set to true.
2142TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002143 Init(NULL);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002144 PeerConnectionInterface::RTCOfferAnswerOptions options;
2145 options.offer_to_receive_audio =
2146 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2147
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002148 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002149 CreateOffer(options));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002150
2151 const cricket::ContentInfo* content =
2152 cricket::GetFirstAudioContent(offer->description());
2153 EXPECT_TRUE(content != NULL);
2154 content = cricket::GetFirstVideoContent(offer->description());
2155 EXPECT_TRUE(content == NULL);
2156}
2157
2158// Test that an offer contains audio and video media content descriptions if
2159// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
2160TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002161 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162 // Test Audio / Video offer.
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002163 PeerConnectionInterface::RTCOfferAnswerOptions options;
2164 options.offer_to_receive_audio =
2165 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2166 options.offer_to_receive_video =
2167 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2168
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002169 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002170 CreateOffer(options));
2171
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002172 const cricket::ContentInfo* content =
2173 cricket::GetFirstAudioContent(offer->description());
jiayl@webrtc.orgc1723202014-09-08 20:44:36 +00002174 EXPECT_TRUE(content != NULL);
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002175
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002176 content = cricket::GetFirstVideoContent(offer->description());
2177 EXPECT_TRUE(content != NULL);
2178
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002179 // Sets constraints to false and verifies that audio/video contents are
2180 // removed.
2181 options.offer_to_receive_audio = 0;
2182 options.offer_to_receive_video = 0;
2183 offer.reset(CreateOffer(options));
2184
2185 content = cricket::GetFirstAudioContent(offer->description());
2186 EXPECT_TRUE(content == NULL);
2187 content = cricket::GetFirstVideoContent(offer->description());
2188 EXPECT_TRUE(content == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002189}
2190
2191// Test that an answer can not be created if the last remote description is not
2192// an offer.
2193TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002194 Init(NULL);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002195 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196 SetLocalDescriptionWithoutError(offer);
2197 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2198 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002199 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002200}
2201
2202// Test that an answer contains the correct media content descriptions when no
2203// constraints have been set.
2204TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002205 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002206 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002207 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002208 SetRemoteDescriptionWithoutError(offer.release());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002209 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002210 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002211 const cricket::ContentInfo* content =
2212 cricket::GetFirstAudioContent(answer->description());
2213 ASSERT_TRUE(content != NULL);
2214 EXPECT_FALSE(content->rejected);
2215
2216 content = cricket::GetFirstVideoContent(answer->description());
2217 ASSERT_TRUE(content != NULL);
2218 EXPECT_FALSE(content->rejected);
2219}
2220
2221// Test that an answer contains the correct media content descriptions when no
2222// constraints have been set and the offer only contain audio.
2223TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002224 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002225 // Create a remote offer with audio only.
2226 cricket::MediaSessionOptions options;
jiayl@webrtc.org7d4891d2014-09-09 21:43:15 +00002227
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002228 rtc::scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002229 CreateRemoteOffer(options));
2230 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
2231 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
2232
2233 SetRemoteDescriptionWithoutError(offer.release());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002234 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002235 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 const cricket::ContentInfo* content =
2237 cricket::GetFirstAudioContent(answer->description());
2238 ASSERT_TRUE(content != NULL);
2239 EXPECT_FALSE(content->rejected);
2240
2241 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
2242}
2243
2244// Test that an answer contains the correct media content descriptions when no
2245// constraints have been set.
2246TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002247 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002249 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 SetRemoteDescriptionWithoutError(offer.release());
2251 // Test with a stream with tracks.
2252 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002253 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002254 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002255 const cricket::ContentInfo* content =
2256 cricket::GetFirstAudioContent(answer->description());
2257 ASSERT_TRUE(content != NULL);
2258 EXPECT_FALSE(content->rejected);
2259
2260 content = cricket::GetFirstVideoContent(answer->description());
2261 ASSERT_TRUE(content != NULL);
2262 EXPECT_FALSE(content->rejected);
2263}
2264
2265// Test that an answer contains the correct media content descriptions when
2266// constraints have been set but no stream is sent.
2267TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002268 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002269 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002270 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002271 SetRemoteDescriptionWithoutError(offer.release());
2272
2273 webrtc::FakeConstraints constraints_no_receive;
2274 constraints_no_receive.SetMandatoryReceiveAudio(false);
2275 constraints_no_receive.SetMandatoryReceiveVideo(false);
2276
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002277 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002278 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002279 const cricket::ContentInfo* content =
2280 cricket::GetFirstAudioContent(answer->description());
2281 ASSERT_TRUE(content != NULL);
2282 EXPECT_TRUE(content->rejected);
2283
2284 content = cricket::GetFirstVideoContent(answer->description());
2285 ASSERT_TRUE(content != NULL);
2286 EXPECT_TRUE(content->rejected);
2287}
2288
2289// Test that an answer contains the correct media content descriptions when
2290// constraints have been set and streams are sent.
2291TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002292 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002293 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002294 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295 SetRemoteDescriptionWithoutError(offer.release());
2296
2297 webrtc::FakeConstraints constraints_no_receive;
2298 constraints_no_receive.SetMandatoryReceiveAudio(false);
2299 constraints_no_receive.SetMandatoryReceiveVideo(false);
2300
2301 // Test with a stream with tracks.
2302 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002303 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002304 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002305
2306 // TODO(perkj): Should the direction be set to SEND_ONLY?
2307 const cricket::ContentInfo* content =
2308 cricket::GetFirstAudioContent(answer->description());
2309 ASSERT_TRUE(content != NULL);
2310 EXPECT_FALSE(content->rejected);
2311
2312 // TODO(perkj): Should the direction be set to SEND_ONLY?
2313 content = cricket::GetFirstVideoContent(answer->description());
2314 ASSERT_TRUE(content != NULL);
2315 EXPECT_FALSE(content->rejected);
2316}
2317
2318TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
2319 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002320 Init(NULL);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002321 PeerConnectionInterface::RTCOfferAnswerOptions options;
2322 options.offer_to_receive_audio =
2323 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
2324 options.voice_activity_detection = false;
2325
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002326 rtc::scoped_ptr<SessionDescriptionInterface> offer(
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002327 CreateOffer(options));
2328
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002329 const cricket::ContentInfo* content =
2330 cricket::GetFirstAudioContent(offer->description());
2331 EXPECT_TRUE(content != NULL);
2332 EXPECT_TRUE(VerifyNoCNCodecs(content));
2333}
2334
2335TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
2336 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002337 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002338 // Create a remote offer with audio and video content.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002339 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002340 SetRemoteDescriptionWithoutError(offer.release());
2341
2342 webrtc::FakeConstraints constraints;
2343 constraints.SetOptionalVAD(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002344 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002345 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346 const cricket::ContentInfo* content =
2347 cricket::GetFirstAudioContent(answer->description());
2348 ASSERT_TRUE(content != NULL);
2349 EXPECT_TRUE(VerifyNoCNCodecs(content));
2350}
2351
2352// This test verifies the call setup when remote answer with audio only and
2353// later updates with video.
2354TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002355 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2357 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2358
2359 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002360 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002361
2362 cricket::MediaSessionOptions options;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002363 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
2364
2365 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2366 // and answer;
2367 SetLocalDescriptionWithoutError(offer);
2368 SetRemoteDescriptionWithoutError(answer);
2369
2370 video_channel_ = media_engine_->GetVideoChannel(0);
2371 voice_channel_ = media_engine_->GetVoiceChannel(0);
2372
2373 ASSERT_TRUE(video_channel_ == NULL);
2374
2375 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
2376 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2377 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
2378
2379 // Let the remote end update the session descriptions, with Audio and Video.
2380 mediastream_signaling_.SendAudioVideoStream2();
2381 CreateAndSetRemoteOfferAndLocalAnswer();
2382
2383 video_channel_ = media_engine_->GetVideoChannel(0);
2384 voice_channel_ = media_engine_->GetVoiceChannel(0);
2385
2386 ASSERT_TRUE(video_channel_ != NULL);
2387 ASSERT_TRUE(voice_channel_ != NULL);
2388
2389 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2390 ASSERT_EQ(1u, video_channel_->send_streams().size());
2391 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2392 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2393 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2394 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2395 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2396 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2397
2398 // Change session back to audio only.
2399 mediastream_signaling_.UseOptionsAudioOnly();
2400 CreateAndSetRemoteOfferAndLocalAnswer();
2401
2402 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2403 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2404 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2405 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2406 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2407}
2408
2409// This test verifies the call setup when remote answer with video only and
2410// later updates with audio.
2411TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002412 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002413 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
2414 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
2415 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002416 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002417
2418 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002419 options.recv_audio = false;
2420 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002421 SessionDescriptionInterface* answer = CreateRemoteAnswer(
2422 offer, options, cricket::SEC_ENABLED);
2423
2424 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
2425 // and answer.
2426 SetLocalDescriptionWithoutError(offer);
2427 SetRemoteDescriptionWithoutError(answer);
2428
2429 video_channel_ = media_engine_->GetVideoChannel(0);
2430 voice_channel_ = media_engine_->GetVoiceChannel(0);
2431
2432 ASSERT_TRUE(voice_channel_ == NULL);
2433 ASSERT_TRUE(video_channel_ != NULL);
2434
2435 EXPECT_EQ(0u, video_channel_->recv_streams().size());
2436 ASSERT_EQ(1u, video_channel_->send_streams().size());
2437 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
2438
2439 // Update the session descriptions, with Audio and Video.
2440 mediastream_signaling_.SendAudioVideoStream2();
2441 CreateAndSetRemoteOfferAndLocalAnswer();
2442
2443 voice_channel_ = media_engine_->GetVoiceChannel(0);
2444 ASSERT_TRUE(voice_channel_ != NULL);
2445
2446 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2447 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2448 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
2449 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
2450
2451 // Change session back to video only.
2452 mediastream_signaling_.UseOptionsVideoOnly();
2453 CreateAndSetRemoteOfferAndLocalAnswer();
2454
2455 video_channel_ = media_engine_->GetVideoChannel(0);
2456 voice_channel_ = media_engine_->GetVoiceChannel(0);
2457
2458 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2459 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
2460 ASSERT_EQ(1u, video_channel_->send_streams().size());
2461 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
2462}
2463
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002464TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002465 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002466 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002467 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002468 VerifyCryptoParams(offer->description());
2469 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002470 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002471 VerifyCryptoParams(answer->description());
2472}
2473
2474TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00002475 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00002476 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002477 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002478 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002479 VerifyNoCryptoParams(offer->description(), false);
2480}
2481
2482TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002483 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002484 VerifyAnswerFromNonCryptoOffer();
2485}
2486
2487TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002488 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002489 VerifyAnswerFromCryptoOffer();
2490}
2491
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002492// This test verifies that setLocalDescription fails if
2493// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2494TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) {
2495 Init(NULL);
2496 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002497 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2498
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002499 std::string sdp;
2500 RemoveIceUfragPwdLines(offer.get(), &sdp);
2501 SessionDescriptionInterface* modified_offer =
2502 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002503 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002504}
2505
2506// This test verifies that setRemoteDescription fails if
2507// no a=ice-ufrag and a=ice-pwd lines are present in the SDP.
2508TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) {
2509 Init(NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002510 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002511 std::string sdp;
2512 RemoveIceUfragPwdLines(offer.get(), &sdp);
2513 SessionDescriptionInterface* modified_offer =
2514 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002515 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002516}
2517
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002518// This test verifies that setLocalDescription fails if local offer has
2519// too short ice ufrag and pwd strings.
2520TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) {
2521 Init(NULL);
2522 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
2523 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002524 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2525
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002526 std::string sdp;
2527 // Modifying ice ufrag and pwd in local offer with strings smaller than the
2528 // recommended values of 4 and 22 bytes respectively.
2529 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2530 SessionDescriptionInterface* modified_offer =
2531 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2532 std::string error;
2533 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2534
2535 // Test with string greater than 256.
2536 sdp.clear();
2537 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2538 &sdp);
2539 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2540 NULL);
2541 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error));
2542}
2543
2544// This test verifies that setRemoteDescription fails if remote offer has
2545// too short ice ufrag and pwd strings.
2546TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) {
2547 Init(NULL);
2548 tdesc_factory_->set_protocol(cricket::ICEPROTO_RFC5245);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002549 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer());
buildbot@webrtc.org7aa1a472014-05-23 17:33:05 +00002550 std::string sdp;
2551 // Modifying ice ufrag and pwd in remote offer with strings smaller than the
2552 // recommended values of 4 and 22 bytes respectively.
2553 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp);
2554 SessionDescriptionInterface* modified_offer =
2555 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
2556 std::string error;
2557 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2558
2559 sdp.clear();
2560 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd,
2561 &sdp);
2562 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp,
2563 NULL);
2564 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error));
2565}
2566
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002567TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
2568 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
2569 // local description is removed by the application, BUNDLE flag should be
2570 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00002571 Init(NULL);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002572 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2573 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002574 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2575
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002576 cricket::SessionDescription* offer_copy =
2577 offer->description()->Copy();
2578 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2579 JsepSessionDescription* modified_offer =
2580 new JsepSessionDescription(JsepSessionDescription::kOffer);
2581 modified_offer->Initialize(offer_copy, "1", "1");
2582
2583 SetLocalDescriptionWithoutError(modified_offer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002584 EXPECT_FALSE(allocator_->flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002585}
2586
2587TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002588 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002589 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002590 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2591 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002592
2593 PeerConnectionInterface::RTCOfferAnswerOptions options;
2594 options.use_rtp_mux = true;
2595
2596 SessionDescriptionInterface* offer = CreateOffer(options);
2597
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002598 SetLocalDescriptionWithoutError(offer);
2599 mediastream_signaling_.SendAudioVideoStream2();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002600 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002601 CreateRemoteAnswer(session_->local_description()));
2602 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2603 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
2604 JsepSessionDescription* modified_answer =
2605 new JsepSessionDescription(JsepSessionDescription::kAnswer);
2606 modified_answer->Initialize(answer_copy, "1", "1");
2607 SetRemoteDescriptionWithoutError(modified_answer);
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002608 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2609 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002610
2611 video_channel_ = media_engine_->GetVideoChannel(0);
2612 voice_channel_ = media_engine_->GetVoiceChannel(0);
2613
2614 ASSERT_EQ(1u, video_channel_->recv_streams().size());
2615 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
2616
2617 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
2618 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
2619
2620 ASSERT_EQ(1u, video_channel_->send_streams().size());
2621 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
2622 ASSERT_EQ(1u, voice_channel_->send_streams().size());
2623 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
2624}
2625
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002626// This test verifies that SetLocalDescription and SetRemoteDescription fails
2627// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
2628TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002629 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002630 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00002631 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE &
2632 allocator_->flags()) == cricket::PORTALLOCATOR_ENABLE_BUNDLE);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002633
2634 PeerConnectionInterface::RTCOfferAnswerOptions options;
2635 options.use_rtp_mux = true;
2636
2637 SessionDescriptionInterface* offer = CreateOffer(options);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002638 std::string offer_str;
2639 offer->ToString(&offer_str);
2640 // Disable rtcp-mux
2641 const std::string rtcp_mux = "rtcp-mux";
2642 const std::string xrtcp_mux = "xrtcp-mux";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002643 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002644 xrtcp_mux.c_str(), xrtcp_mux.length(),
2645 &offer_str);
2646 JsepSessionDescription *local_offer =
2647 new JsepSessionDescription(JsepSessionDescription::kOffer);
2648 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002649 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002650 JsepSessionDescription *remote_offer =
2651 new JsepSessionDescription(JsepSessionDescription::kOffer);
2652 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002653 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002654 // Trying unmodified SDP.
2655 SetLocalDescriptionWithoutError(offer);
2656}
2657
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002658TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002659 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002660 mediastream_signaling_.SendAudioVideoStream1();
2661 CreateAndSetRemoteOfferAndLocalAnswer();
2662 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2663 ASSERT_TRUE(channel != NULL);
2664 ASSERT_EQ(1u, channel->recv_streams().size());
2665 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2666 double left_vol, right_vol;
2667 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2668 EXPECT_EQ(1, left_vol);
2669 EXPECT_EQ(1, right_vol);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002670 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002671 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002672 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2673 EXPECT_EQ(0, left_vol);
2674 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002675 EXPECT_EQ(0, renderer->channel_id());
2676 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002677 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2678 EXPECT_EQ(1, left_vol);
2679 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002680 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002681}
2682
2683TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002684 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002685 mediastream_signaling_.SendAudioVideoStream1();
2686 CreateAndSetRemoteOfferAndLocalAnswer();
2687 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2688 ASSERT_TRUE(channel != NULL);
2689 ASSERT_EQ(1u, channel->send_streams().size());
2690 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2691 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2692
2693 cricket::AudioOptions options;
2694 options.echo_cancellation.Set(true);
2695
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002696 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002697 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002698 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2699 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002700 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002701 EXPECT_TRUE(renderer->sink() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002702
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002703 // This will trigger SetSink(NULL) to the |renderer|.
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002704 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002705 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2706 bool value;
2707 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2708 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002709 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002710 EXPECT_TRUE(renderer->sink() == NULL);
2711}
2712
2713TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) {
2714 Init(NULL);
2715 mediastream_signaling_.SendAudioVideoStream1();
2716 CreateAndSetRemoteOfferAndLocalAnswer();
2717 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2718 ASSERT_TRUE(channel != NULL);
2719 ASSERT_EQ(1u, channel->send_streams().size());
2720 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2721
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002722 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
henrike@webrtc.orga7b98182014-02-21 15:51:43 +00002723 cricket::AudioOptions options;
2724 session_->SetAudioSend(send_ssrc, true, options, renderer.get());
2725 EXPECT_TRUE(renderer->sink() != NULL);
2726
2727 // Delete the |renderer| and it will trigger OnClose() to the sink, and this
2728 // will invalidate the |renderer_| pointer in the sink and prevent getting a
2729 // SetSink(NULL) callback afterwards.
2730 renderer.reset();
2731
2732 // This will trigger SetSink(NULL) if no OnClose() callback.
2733 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002734}
2735
2736TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002737 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002738 mediastream_signaling_.SendAudioVideoStream1();
2739 CreateAndSetRemoteOfferAndLocalAnswer();
2740 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2741 ASSERT_TRUE(channel != NULL);
2742 ASSERT_LT(0u, channel->renderers().size());
2743 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2744 ASSERT_EQ(1u, channel->recv_streams().size());
2745 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2746 cricket::FakeVideoRenderer renderer;
2747 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2748 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2749 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2750 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2751}
2752
2753TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002754 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002755 mediastream_signaling_.SendAudioVideoStream1();
2756 CreateAndSetRemoteOfferAndLocalAnswer();
2757 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2758 ASSERT_TRUE(channel != NULL);
2759 ASSERT_EQ(1u, channel->send_streams().size());
2760 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2761 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2762 cricket::VideoOptions* options = NULL;
2763 session_->SetVideoSend(send_ssrc, false, options);
2764 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2765 session_->SetVideoSend(send_ssrc, true, options);
2766 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2767}
2768
2769TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2770 TestCanInsertDtmf(false);
2771}
2772
2773TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2774 TestCanInsertDtmf(true);
2775}
2776
2777TEST_F(WebRtcSessionTest, InsertDtmf) {
2778 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002779 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002780 mediastream_signaling_.SendAudioVideoStream1();
2781 CreateAndSetRemoteOfferAndLocalAnswer();
2782 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2783 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2784
2785 // Insert DTMF
2786 const int expected_flags = DF_SEND;
2787 const int expected_duration = 90;
2788 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2789 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2790 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2791
2792 // Verify
2793 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2794 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2795 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2796 expected_duration, expected_flags));
2797 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2798 expected_duration, expected_flags));
2799 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2800 expected_duration, expected_flags));
2801}
2802
2803// This test verifies the |initiator| flag when session initiates the call.
2804TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002805 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002806 EXPECT_FALSE(session_->initiator());
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002807 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002808 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2809 SetLocalDescriptionWithoutError(offer);
2810 EXPECT_TRUE(session_->initiator());
2811 SetRemoteDescriptionWithoutError(answer);
2812 EXPECT_TRUE(session_->initiator());
2813}
2814
2815// This test verifies the |initiator| flag when session receives the call.
2816TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002817 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002818 EXPECT_FALSE(session_->initiator());
2819 SessionDescriptionInterface* offer = CreateRemoteOffer();
2820 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002821 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002822
2823 EXPECT_FALSE(session_->initiator());
2824 SetLocalDescriptionWithoutError(answer);
2825 EXPECT_FALSE(session_->initiator());
2826}
2827
2828// This test verifies the ice protocol type at initiator of the call
2829// if |a=ice-options:google-ice| is present in answer.
2830TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002831 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002832 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002833 SessionDescriptionInterface* offer = CreateOffer();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002834 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002835 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002836 SetLocalDescriptionWithoutError(offer);
2837 std::string sdp;
2838 EXPECT_TRUE(answer->ToString(&sdp));
2839 // Adding ice-options to the session level.
2840 InjectAfter("t=0 0\r\n",
2841 "a=ice-options:google-ice\r\n",
2842 &sdp);
2843 SessionDescriptionInterface* answer_with_gice =
2844 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2845 SetRemoteDescriptionWithoutError(answer_with_gice);
2846 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2847 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2848}
2849
2850// This test verifies the ice protocol type at initiator of the call
2851// if ICE RFC5245 is supported in answer.
2852TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002853 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002854 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002855 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002856 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2857 SetLocalDescriptionWithoutError(offer);
2858
2859 SetRemoteDescriptionWithoutError(answer);
2860 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2861 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2862}
2863
2864// This test verifies the ice protocol type at receiver side of the call if
2865// receiver decides to use google-ice.
2866TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002867 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002868 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002869 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002870 SetRemoteDescriptionWithoutError(offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002871 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002872 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002873 std::string sdp;
2874 EXPECT_TRUE(answer->ToString(&sdp));
2875 // Adding ice-options to the session level.
2876 InjectAfter("t=0 0\r\n",
2877 "a=ice-options:google-ice\r\n",
2878 &sdp);
2879 SessionDescriptionInterface* answer_with_gice =
2880 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2881 SetLocalDescriptionWithoutError(answer_with_gice);
2882 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2883 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2884}
2885
2886// This test verifies the ice protocol type at receiver side of the call if
2887// receiver decides to use ice RFC 5245.
2888TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002889 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002890 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002891 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002892 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002893 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002894 SetLocalDescriptionWithoutError(answer);
2895 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2896 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2897}
2898
2899// This test verifies the session state when ICE RFC5245 in offer and
2900// ICE google-ice in answer.
2901TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002902 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002903 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002904 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
2905
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002906 std::string offer_str;
2907 offer->ToString(&offer_str);
2908 // Disable google-ice
2909 const std::string gice_option = "google-ice";
2910 const std::string xgoogle_xice = "xgoogle-xice";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002911 rtc::replace_substrs(gice_option.c_str(), gice_option.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002912 xgoogle_xice.c_str(), xgoogle_xice.length(),
2913 &offer_str);
2914 JsepSessionDescription *ice_only_offer =
2915 new JsepSessionDescription(JsepSessionDescription::kOffer);
2916 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2917 SetLocalDescriptionWithoutError(ice_only_offer);
2918 std::string original_offer_sdp;
2919 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002920 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002921 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002922 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002923 SetRemoteDescriptionPranswerExpectError(kPushDownTDFailed,
2924 pranswer_with_gice);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002925 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002926 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002927 original_offer_sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002928 SetRemoteDescriptionAnswerExpectError(kPushDownTDFailed,
2929 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002930}
2931
2932// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2933TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002934 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002935 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00002936 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002937 SetLocalDescriptionWithoutError(offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002938 rtc::scoped_ptr<SessionDescriptionInterface> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002939 CreateRemoteAnswer(session_->local_description()));
2940
2941 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2942 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002943 JsepSessionDescription* modified_answer =
2944 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002945
2946 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2947 answer->session_id(),
2948 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002949 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002950
wu@webrtc.org4e393072014-04-07 17:04:35 +00002951 // Different content names.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002952 std::string sdp;
2953 EXPECT_TRUE(answer->ToString(&sdp));
2954 const std::string kAudioMid = "a=mid:audio";
2955 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002956 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002957 kAudioMidReplaceStr.c_str(),
2958 kAudioMidReplaceStr.length(),
2959 &sdp);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002960 SessionDescriptionInterface* modified_answer1 =
2961 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002962 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002963
wu@webrtc.org4e393072014-04-07 17:04:35 +00002964 // Different media types.
2965 EXPECT_TRUE(answer->ToString(&sdp));
2966 const std::string kAudioMline = "m=audio";
2967 const std::string kAudioMlineReplaceStr = "m=video";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002968 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(),
wu@webrtc.org4e393072014-04-07 17:04:35 +00002969 kAudioMlineReplaceStr.c_str(),
2970 kAudioMlineReplaceStr.length(),
2971 &sdp);
2972 SessionDescriptionInterface* modified_answer2 =
2973 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2974 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2);
2975
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002976 SetRemoteDescriptionWithoutError(answer.release());
2977}
2978
2979// Verifying remote offer and local answer have matching m-lines as per
2980// RFC 3264.
2981TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002982 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002983 mediastream_signaling_.SendAudioVideoStream1();
2984 SessionDescriptionInterface* offer = CreateRemoteOffer();
2985 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002986 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002987
2988 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2989 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002990 JsepSessionDescription* modified_answer =
2991 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002992
2993 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2994 answer->session_id(),
2995 answer->session_version()));
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00002996 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002997 SetLocalDescriptionWithoutError(answer);
2998}
2999
3000// This test verifies that WebRtcSession does not start candidate allocation
3001// before SetLocalDescription is called.
3002TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00003003 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003004 mediastream_signaling_.SendAudioVideoStream1();
3005 SessionDescriptionInterface* offer = CreateRemoteOffer();
3006 cricket::Candidate candidate;
3007 candidate.set_component(1);
3008 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
3009 candidate);
3010 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
3011 cricket::Candidate candidate1;
3012 candidate1.set_component(1);
3013 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
3014 candidate1);
3015 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
3016 SetRemoteDescriptionWithoutError(offer);
3017 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
3018 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
3019
3020 // Pump for 1 second and verify that no candidates are generated.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003021 rtc::Thread::Current()->ProcessMessages(1000);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003022 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
3023 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
3024
wu@webrtc.org91053e72013-08-10 07:18:04 +00003025 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003026 SetLocalDescriptionWithoutError(answer);
3027 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
3028 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
3029 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
3030}
3031
3032// This test verifies that crypto parameter is updated in local session
3033// description as per security policy set in MediaSessionDescriptionFactory.
3034TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00003035 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003036 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003037 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003038
3039 // Making sure SetLocalDescription correctly sets crypto value in
3040 // SessionDescription object after de-serialization of sdp string. The value
3041 // will be set as per MediaSessionDescriptionFactory.
3042 std::string offer_str;
3043 offer->ToString(&offer_str);
3044 SessionDescriptionInterface* jsep_offer_str =
3045 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3046 SetLocalDescriptionWithoutError(jsep_offer_str);
3047 EXPECT_TRUE(session_->voice_channel()->secure_required());
3048 EXPECT_TRUE(session_->video_channel()->secure_required());
3049}
3050
3051// This test verifies the crypto parameter when security is disabled.
3052TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org97077a32013-10-25 21:18:33 +00003053 options_.disable_encryption = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003054 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003055 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003056 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003057
3058 // Making sure SetLocalDescription correctly sets crypto value in
3059 // SessionDescription object after de-serialization of sdp string. The value
3060 // will be set as per MediaSessionDescriptionFactory.
3061 std::string offer_str;
3062 offer->ToString(&offer_str);
3063 SessionDescriptionInterface *jsep_offer_str =
3064 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
3065 SetLocalDescriptionWithoutError(jsep_offer_str);
3066 EXPECT_FALSE(session_->voice_channel()->secure_required());
3067 EXPECT_FALSE(session_->video_channel()->secure_required());
3068}
3069
3070// This test verifies that an answer contains new ufrag and password if an offer
3071// with new ufrag and password is received.
3072TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00003073 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003074 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003075 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003076 rtc::scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003077 CreateRemoteOffer(options));
3078 SetRemoteDescriptionWithoutError(offer.release());
3079
3080 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003081 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003082 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003083 SetLocalDescriptionWithoutError(answer.release());
3084
3085 // Receive an offer with new ufrag and password.
3086 options.transport_options.ice_restart = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003087 rtc::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003088 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003089 SetRemoteDescriptionWithoutError(updated_offer1.release());
3090
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003091 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003092 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003093
3094 CompareIceUfragAndPassword(updated_answer1->description(),
3095 session_->local_description()->description(),
3096 false);
3097
3098 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003099}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003100
wu@webrtc.org91053e72013-08-10 07:18:04 +00003101// This test verifies that an answer contains old ufrag and password if an offer
3102// with old ufrag and password is received.
3103TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
3104 Init(NULL);
3105 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003106 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003107 rtc::scoped_ptr<JsepSessionDescription> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003108 CreateRemoteOffer(options));
3109 SetRemoteDescriptionWithoutError(offer.release());
3110
3111 mediastream_signaling_.SendAudioVideoStream1();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003112 rtc::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003113 CreateAnswer(NULL));
3114 SetLocalDescriptionWithoutError(answer.release());
3115
3116 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003117 options.transport_options.ice_restart = false;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003118 rtc::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003119 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003120 SetRemoteDescriptionWithoutError(updated_offer2.release());
3121
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003122 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00003123 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003124
3125 CompareIceUfragAndPassword(updated_answer2->description(),
3126 session_->local_description()->description(),
3127 true);
3128
3129 SetLocalDescriptionWithoutError(updated_answer2.release());
3130}
3131
3132TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00003133 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003134 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003135 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003136 const std::string session_id_orig = offer->session_id();
3137 const std::string session_version_orig = offer->session_version();
3138 SetLocalDescriptionWithoutError(offer);
3139
3140 video_channel_ = media_engine_->GetVideoChannel(0);
3141 video_channel_->set_fail_set_send_codecs(true);
3142
3143 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00003144 SessionDescriptionInterface* answer =
3145 CreateRemoteAnswer(session_->local_description());
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003146 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003147}
3148
3149// Runs the loopback call test with BUNDLE and STUN disabled.
3150TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
3151 // Lets try with only UDP ports.
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00003152 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003153 cricket::PORTALLOCATOR_DISABLE_TCP |
3154 cricket::PORTALLOCATOR_DISABLE_STUN |
3155 cricket::PORTALLOCATOR_DISABLE_RELAY);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003156 TestLoopbackCall();
3157}
3158
guoweis@webrtc.org7169afd2014-12-04 17:59:29 +00003159TEST_F(WebRtcSessionTest, TestIceStatesBasicIPv6) {
3160 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
3161 cricket::PORTALLOCATOR_DISABLE_TCP |
3162 cricket::PORTALLOCATOR_DISABLE_STUN |
3163 cricket::PORTALLOCATOR_ENABLE_IPV6 |
3164 cricket::PORTALLOCATOR_DISABLE_RELAY);
3165
3166 // best connection is IPv6 since it has higher network preference.
3167 LoopbackNetworkConfiguration config;
3168 config.test_ipv6_network_ = true;
3169 config.best_connection_after_initial_ice_converged_ =
3170 LoopbackNetworkConfiguration::ExpectedBestConnection(0, 1);
3171
3172 TestLoopbackCall(config);
3173}
3174
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00003175// Runs the loopback call test with BUNDLE and STUN enabled.
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003176TEST_F(WebRtcSessionTest, TestIceStatesBundle) {
buildbot@webrtc.org41451d42014-05-03 05:39:45 +00003177 allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003178 cricket::PORTALLOCATOR_ENABLE_BUNDLE |
mallinath@webrtc.orgd3dc4242014-03-01 00:05:52 +00003179 cricket::PORTALLOCATOR_DISABLE_TCP |
mallinath@webrtc.org385857d2014-02-14 00:56:12 +00003180 cricket::PORTALLOCATOR_DISABLE_RELAY);
3181 TestLoopbackCall();
3182}
3183
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003184TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00003185 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003186 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003187 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003188
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003189 cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
3190 std::string error_code_str = "ERROR_CONTENT";
3191 std::string error_desc = "Fake session error description.";
3192 session_->SetError(error_code, error_desc);
3193
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003194 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
3195 SessionDescriptionInterface* answer =
3196 CreateRemoteAnswer(offer, options);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003197
3198 std::string action;
3199 std::ostringstream session_error_msg;
3200 session_error_msg << kSessionError << error_code_str << ". ";
3201 session_error_msg << kSessionErrorDesc << error_desc << ".";
3202 SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
3203 SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003204}
3205
3206TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
3207 constraints_.reset(new FakeConstraints());
3208 constraints_->AddOptional(
3209 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003210 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003211
3212 SetLocalDescriptionWithDataChannel();
3213 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3214}
3215
3216TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003217 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003218
3219 constraints_.reset(new FakeConstraints());
3220 constraints_->AddOptional(
3221 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org97077a32013-10-25 21:18:33 +00003222 options_.disable_sctp_data_channels = false;
3223
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003224 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003225
3226 SetLocalDescriptionWithDataChannel();
3227 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
3228}
3229
wu@webrtc.org967bfff2013-09-19 05:49:50 +00003230TEST_F(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003231 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org967bfff2013-09-19 05:49:50 +00003232
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003233 InitWithDtls();
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003234
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003235 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003236 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003237 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL);
3238}
3239
3240TEST_F(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003241 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003242 SetFactoryDtlsSrtp();
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003243 InitWithDtls();
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003244
3245 // Create remote offer with SCTP.
3246 cricket::MediaSessionOptions options;
3247 options.data_channel_type = cricket::DCT_SCTP;
3248 JsepSessionDescription* offer =
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003249 CreateRemoteOffer(options, cricket::SEC_DISABLED);
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003250 SetRemoteDescriptionWithoutError(offer);
3251
3252 // Verifies the answer contains SCTP.
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003253 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
mallinath@webrtc.org1112c302013-09-23 20:34:45 +00003254 EXPECT_TRUE(answer != NULL);
3255 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL);
3256 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL);
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003257}
3258
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003259TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
3260 constraints_.reset(new FakeConstraints());
3261 constraints_->AddOptional(
sergeyu@chromium.orga59696b2013-09-13 23:48:58 +00003262 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003263 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003264
3265 SetLocalDescriptionWithDataChannel();
3266 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3267}
3268
3269TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003270 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003271
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003272 InitWithDtls();
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003273
3274 SetLocalDescriptionWithDataChannel();
3275 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
3276}
wu@webrtc.org91053e72013-08-10 07:18:04 +00003277
wu@webrtc.org97077a32013-10-25 21:18:33 +00003278TEST_F(WebRtcSessionTest, TestDisableSctpDataChannels) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003279 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org97077a32013-10-25 21:18:33 +00003280 options_.disable_sctp_data_channels = true;
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003281 InitWithDtls();
wu@webrtc.org97077a32013-10-25 21:18:33 +00003282
3283 SetLocalDescriptionWithDataChannel();
3284 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
3285}
3286
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003287TEST_F(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003288 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003289 const int new_send_port = 9998;
3290 const int new_recv_port = 7775;
3291
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003292 InitWithDtls();
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003293 SetFactoryDtlsSrtp();
3294
3295 // By default, don't actually add the codecs to desc_factory_; they don't
3296 // actually get serialized for SCTP in BuildMediaDescription(). Instead,
3297 // let the session description get parsed. That'll get the proper codecs
3298 // into the stream.
3299 cricket::MediaSessionOptions options;
3300 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort(
3301 "stream1", new_send_port, options);
3302
3303 // SetRemoteDescription will take the ownership of the offer.
3304 SetRemoteDescriptionWithoutError(offer);
3305
3306 SessionDescriptionInterface* answer = ChangeSDPSctpPort(
3307 new_recv_port, CreateAnswer(NULL));
3308 ASSERT_TRUE(answer != NULL);
3309
3310 // Now set the local description, which'll take ownership of the answer.
3311 SetLocalDescriptionWithoutError(answer);
3312
3313 // TEST PLAN: Set the port number to something new, set it in the SDP,
3314 // and pass it all the way down.
henrika@webrtc.orgaebb1ad2014-01-14 10:00:58 +00003315 webrtc::InternalDataChannelInit dci;
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003316 dci.reliable = true;
3317 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003318 rtc::scoped_refptr<webrtc::DataChannel> dc =
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00003319 session_->CreateDataChannel("datachannel", &dci);
3320
3321 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0);
3322 int portnum = -1;
3323 ASSERT_TRUE(ch != NULL);
3324 ASSERT_EQ(1UL, ch->send_codecs().size());
3325 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id);
3326 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3327 ch->send_codecs()[0].name.c_str()));
3328 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort,
3329 &portnum));
3330 EXPECT_EQ(new_send_port, portnum);
3331
3332 ASSERT_EQ(1UL, ch->recv_codecs().size());
3333 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id);
3334 EXPECT_TRUE(!strcmp(cricket::kGoogleSctpDataCodecName,
3335 ch->recv_codecs()[0].name.c_str()));
3336 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort,
3337 &portnum));
3338 EXPECT_EQ(new_recv_port, portnum);
3339}
3340
wu@webrtc.org91053e72013-08-10 07:18:04 +00003341// Verifies that CreateOffer succeeds when CreateOffer is called before async
3342// identity generation is finished.
3343TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003344 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003345 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003346
3347 EXPECT_TRUE(session_->waiting_for_identity());
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003348 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003349 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
3350
wu@webrtc.org91053e72013-08-10 07:18:04 +00003351 EXPECT_TRUE(offer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003352 VerifyNoCryptoParams(offer->description(), true);
3353 VerifyFingerprintStatus(offer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003354}
3355
3356// Verifies that CreateAnswer succeeds when CreateOffer is called before async
3357// identity generation is finished.
3358TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003359 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003360 InitWithDtls();
3361 SetFactoryDtlsSrtp();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003362
3363 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003364 options.recv_video = true;
wu@webrtc.org91053e72013-08-10 07:18:04 +00003365 scoped_ptr<JsepSessionDescription> offer(
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003366 CreateRemoteOffer(options, cricket::SEC_DISABLED));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003367 ASSERT_TRUE(offer.get() != NULL);
3368 SetRemoteDescriptionWithoutError(offer.release());
3369
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003370 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
wu@webrtc.org91053e72013-08-10 07:18:04 +00003371 EXPECT_TRUE(answer != NULL);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003372 VerifyNoCryptoParams(answer->description(), true);
3373 VerifyFingerprintStatus(answer->description(), true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003374}
3375
3376// Verifies that CreateOffer succeeds when CreateOffer is called after async
3377// identity generation is finished.
3378TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003379 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003380 InitWithDtls();
wu@webrtc.org91053e72013-08-10 07:18:04 +00003381
3382 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003383
3384 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003385 EXPECT_TRUE(offer != NULL);
3386}
3387
3388// Verifies that CreateOffer fails when CreateOffer is called after async
3389// identity generation fails.
3390TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003391 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
henrike@webrtc.org7666db72013-08-22 14:45:42 +00003392 InitWithDtls(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003393
3394 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003395
3396 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
wu@webrtc.org91053e72013-08-10 07:18:04 +00003397 EXPECT_TRUE(offer == NULL);
3398}
3399
3400// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
3401// before async identity generation is finished.
3402TEST_F(WebRtcSessionTest,
3403 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003404 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003405 VerifyMultipleAsyncCreateDescription(
3406 true, CreateSessionDescriptionRequest::kOffer);
3407}
3408
3409// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
3410// before async identity generation fails.
3411TEST_F(WebRtcSessionTest,
3412 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003413 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003414 VerifyMultipleAsyncCreateDescription(
3415 false, CreateSessionDescriptionRequest::kOffer);
3416}
3417
3418// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
3419// before async identity generation is finished.
3420TEST_F(WebRtcSessionTest,
3421 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003422 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003423 VerifyMultipleAsyncCreateDescription(
3424 true, CreateSessionDescriptionRequest::kAnswer);
3425}
3426
3427// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
3428// before async identity generation fails.
3429TEST_F(WebRtcSessionTest,
3430 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003431 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
wu@webrtc.org91053e72013-08-10 07:18:04 +00003432 VerifyMultipleAsyncCreateDescription(
3433 false, CreateSessionDescriptionRequest::kAnswer);
3434}
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003435
3436// Verifies that setRemoteDescription fails when DTLS is disabled and the remote
3437// offer has no SDES crypto but only DTLS fingerprint.
3438TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) {
3439 // Init without DTLS.
3440 Init(NULL);
3441 // Create a remote offer with secured transport disabled.
3442 cricket::MediaSessionOptions options;
3443 JsepSessionDescription* offer(CreateRemoteOffer(
3444 options, cricket::SEC_DISABLED));
3445 // Adds a DTLS fingerprint to the remote offer.
3446 cricket::SessionDescription* sdp = offer->description();
3447 TransportInfo* audio = sdp->GetTransportInfoByName("audio");
3448 ASSERT_TRUE(audio != NULL);
3449 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL);
3450 audio->description.identity_fingerprint.reset(
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003451 rtc::SSLFingerprint::CreateFromRfc4572(
3452 rtc::DIGEST_SHA_256, kFakeDtlsFingerprint));
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +00003453 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto,
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +00003454 offer);
mallinath@webrtc.orga27be8e2013-09-27 23:04:10 +00003455}
3456
wu@webrtc.orgde305012013-10-31 15:40:38 +00003457// This test verifies DSCP is properly applied on the media channels.
3458TEST_F(WebRtcSessionTest, TestDscpConstraint) {
3459 constraints_.reset(new FakeConstraints());
3460 constraints_->AddOptional(
3461 webrtc::MediaConstraintsInterface::kEnableDscp, true);
3462 Init(NULL);
3463 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003464 SessionDescriptionInterface* offer = CreateOffer();
wu@webrtc.orgde305012013-10-31 15:40:38 +00003465
3466 SetLocalDescriptionWithoutError(offer);
3467
3468 video_channel_ = media_engine_->GetVideoChannel(0);
3469 voice_channel_ = media_engine_->GetVoiceChannel(0);
3470
3471 ASSERT_TRUE(video_channel_ != NULL);
3472 ASSERT_TRUE(voice_channel_ != NULL);
3473 cricket::AudioOptions audio_options;
3474 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
3475 cricket::VideoOptions video_options;
3476 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3477 EXPECT_TRUE(audio_options.dscp.IsSet());
3478 EXPECT_TRUE(audio_options.dscp.GetWithDefaultIfUnset(false));
3479 EXPECT_TRUE(video_options.dscp.IsSet());
3480 EXPECT_TRUE(video_options.dscp.GetWithDefaultIfUnset(false));
3481}
3482
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003483TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) {
3484 constraints_.reset(new FakeConstraints());
3485 constraints_->AddOptional(
3486 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate,
3487 true);
3488 Init(NULL);
3489 mediastream_signaling_.SendAudioVideoStream1();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003490 SessionDescriptionInterface* offer = CreateOffer();
henrike@webrtc.org6e3dbc22014-03-25 17:09:47 +00003491
3492 SetLocalDescriptionWithoutError(offer);
3493
3494 video_channel_ = media_engine_->GetVideoChannel(0);
3495
3496 ASSERT_TRUE(video_channel_ != NULL);
3497 cricket::VideoOptions video_options;
3498 EXPECT_TRUE(video_channel_->GetOptions(&video_options));
3499 EXPECT_TRUE(
3500 video_options.suspend_below_min_bitrate.GetWithDefaultIfUnset(false));
3501}
3502
buildbot@webrtc.org53df88c2014-08-07 22:46:01 +00003503TEST_F(WebRtcSessionTest, TestNumUnsignalledRecvStreamsConstraint) {
3504 // Number of unsignalled receiving streams should be between 0 and
3505 // kMaxUnsignalledRecvStreams.
3506 SetAndVerifyNumUnsignalledRecvStreams(10, 10);
3507 SetAndVerifyNumUnsignalledRecvStreams(kMaxUnsignalledRecvStreams + 1,
3508 kMaxUnsignalledRecvStreams);
3509 SetAndVerifyNumUnsignalledRecvStreams(-1, 0);
3510}
3511
buildbot@webrtc.orgb4c7b092014-08-25 12:11:58 +00003512TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) {
3513 constraints_.reset(new FakeConstraints());
3514 constraints_->AddOptional(
3515 webrtc::MediaConstraintsInterface::kCombinedAudioVideoBwe,
3516 true);
3517 Init(NULL);
3518 mediastream_signaling_.SendAudioVideoStream1();
3519 SessionDescriptionInterface* offer = CreateOffer();
3520
3521 SetLocalDescriptionWithoutError(offer);
3522
3523 voice_channel_ = media_engine_->GetVoiceChannel(0);
3524
3525 ASSERT_TRUE(voice_channel_ != NULL);
3526 cricket::AudioOptions audio_options;
3527 EXPECT_TRUE(voice_channel_->GetOptions(&audio_options));
3528 EXPECT_TRUE(
3529 audio_options.combined_audio_video_bwe.GetWithDefaultIfUnset(false));
3530}
3531
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003532// Tests that we can renegotiate new media content with ICE candidates in the
3533// new remote SDP.
3534TEST_F(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003535 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003536 InitWithDtls();
3537 SetFactoryDtlsSrtp();
3538
3539 mediastream_signaling_.UseOptionsAudioOnly();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003540 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003541 SetLocalDescriptionWithoutError(offer);
3542
3543 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
3544 SetRemoteDescriptionWithoutError(answer);
3545
3546 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003547 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003548 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
3549
3550 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003551 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003552 candidate1.set_component(1);
3553 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
3554 candidate1);
3555 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
3556 SetRemoteDescriptionWithoutError(offer);
3557
3558 answer = CreateAnswer(NULL);
3559 SetLocalDescriptionWithoutError(answer);
3560}
3561
3562// Tests that we can renegotiate new media content with ICE candidates separated
3563// from the remote SDP.
3564TEST_F(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003565 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp);
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003566 InitWithDtls();
3567 SetFactoryDtlsSrtp();
3568
3569 mediastream_signaling_.UseOptionsAudioOnly();
jiayl@webrtc.orgb18bf5e2014-08-04 18:34:16 +00003570 SessionDescriptionInterface* offer = CreateOffer();
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003571 SetLocalDescriptionWithoutError(offer);
3572
3573 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
3574 SetRemoteDescriptionWithoutError(answer);
3575
3576 cricket::MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00003577 options.recv_video = true;
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003578 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
3579 SetRemoteDescriptionWithoutError(offer);
3580
3581 cricket::Candidate candidate1;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00003582 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000));
jiayl@webrtc.orge10d28c2014-07-17 17:07:49 +00003583 candidate1.set_component(1);
3584 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1,
3585 candidate1);
3586 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate));
3587
3588 answer = CreateAnswer(NULL);
3589 SetLocalDescriptionWithoutError(answer);
3590}
3591
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003592// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
3593// currently fails because upon disconnection and reconnection OnIceComplete is
3594// called more than once without returning to IceGatheringGathering.