blob: 7c8af5216cb7ab3bef222faeffbb3f1b6059df54 [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"
33#include "talk/app/webrtc/videotrack.h"
34#include "talk/app/webrtc/test/fakeconstraints.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000035#include "talk/app/webrtc/test/fakedtlsidentityservice.h"
36#include "talk/app/webrtc/test/fakemediastreamsignaling.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"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039#include "talk/base/fakenetwork.h"
40#include "talk/base/firewallsocketserver.h"
41#include "talk/base/gunit.h"
42#include "talk/base/logging.h"
43#include "talk/base/network.h"
44#include "talk/base/physicalsocketserver.h"
45#include "talk/base/sslstreamadapter.h"
46#include "talk/base/stringutils.h"
47#include "talk/base/thread.h"
48#include "talk/base/virtualsocketserver.h"
49#include "talk/media/base/fakemediaengine.h"
50#include "talk/media/base/fakevideorenderer.h"
51#include "talk/media/base/mediachannel.h"
52#include "talk/media/devices/fakedevicemanager.h"
53#include "talk/p2p/base/stunserver.h"
54#include "talk/p2p/base/teststunserver.h"
55#include "talk/p2p/client/basicportallocator.h"
56#include "talk/session/media/channelmanager.h"
57#include "talk/session/media/mediasession.h"
58
59#define MAYBE_SKIP_TEST(feature) \
60 if (!(feature())) { \
61 LOG(LS_INFO) << "Feature disabled... skipping"; \
62 return; \
63 }
64
65using cricket::BaseSession;
66using cricket::DF_PLAY;
67using cricket::DF_SEND;
68using cricket::FakeVoiceMediaChannel;
69using cricket::NS_GINGLE_P2P;
70using cricket::NS_JINGLE_ICE_UDP;
71using cricket::TransportInfo;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072using talk_base::SocketAddress;
73using talk_base::scoped_ptr;
74using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000075using webrtc::CreateSessionDescriptionObserver;
76using webrtc::CreateSessionDescriptionRequest;
77using webrtc::DTLSIdentityRequestObserver;
78using webrtc::DTLSIdentityServiceInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079using webrtc::FakeConstraints;
80using webrtc::IceCandidateCollection;
81using webrtc::JsepIceCandidate;
82using webrtc::JsepSessionDescription;
83using webrtc::PeerConnectionInterface;
84using webrtc::SessionDescriptionInterface;
85using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000086using webrtc::WebRtcSession;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::kMlineMismatch;
88using webrtc::kSdpWithoutCrypto;
89using webrtc::kSessionError;
90using webrtc::kSetLocalSdpFailed;
91using webrtc::kSetRemoteSdpFailed;
92using webrtc::kPushDownAnswerTDFailed;
93using webrtc::kPushDownPranswerTDFailed;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000094using webrtc::kBundleWithoutRtcpMux;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095
96static const SocketAddress kClientAddr1("11.11.11.11", 0);
97static const SocketAddress kClientAddr2("22.22.22.22", 0);
98static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
99
100static const char kSessionVersion[] = "1";
101
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102// Media index of candidates belonging to the first media content.
103static const int kMediaContentIndex0 = 0;
104static const char kMediaContentName0[] = "audio";
105
106// Media index of candidates belonging to the second media content.
107static const int kMediaContentIndex1 = 1;
108static const char kMediaContentName1[] = "video";
109
110static const int kIceCandidatesTimeout = 10000;
111
112static const cricket::AudioCodec
113 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
114static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
115static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
116
117// Add some extra |newlines| to the |message| after |line|.
118static void InjectAfter(const std::string& line,
119 const std::string& newlines,
120 std::string* message) {
121 const std::string tmp = line + newlines;
122 talk_base::replace_substrs(line.c_str(), line.length(),
123 tmp.c_str(), tmp.length(), message);
124}
125
126class MockIceObserver : public webrtc::IceObserver {
127 public:
128 MockIceObserver()
129 : oncandidatesready_(false),
130 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
131 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
132 }
133
134 virtual void OnIceConnectionChange(
135 PeerConnectionInterface::IceConnectionState new_state) {
136 ice_connection_state_ = new_state;
137 }
138 virtual void OnIceGatheringChange(
139 PeerConnectionInterface::IceGatheringState new_state) {
140 // We can never transition back to "new".
141 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
142 ice_gathering_state_ = new_state;
143
144 // oncandidatesready_ really means "ICE gathering is complete".
145 // This if statement ensures that this value remains correct when we
146 // transition from kIceGatheringComplete to kIceGatheringGathering.
147 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
148 oncandidatesready_ = false;
149 }
150 }
151
152 // Found a new candidate.
153 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
154 if (candidate->sdp_mline_index() == kMediaContentIndex0) {
155 mline_0_candidates_.push_back(candidate->candidate());
156 } else if (candidate->sdp_mline_index() == kMediaContentIndex1) {
157 mline_1_candidates_.push_back(candidate->candidate());
158 }
159 // The ICE gathering state should always be Gathering when a candidate is
160 // received (or possibly Completed in the case of the final candidate).
161 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
162 }
163
164 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
165 virtual void OnIceComplete() {
166 EXPECT_FALSE(oncandidatesready_);
167 oncandidatesready_ = true;
168
169 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
170 // be called approximately simultaneously. For ease of testing, this
171 // check additionally requires that they be called in the above order.
172 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
173 ice_gathering_state_);
174 }
175
176 bool oncandidatesready_;
177 std::vector<cricket::Candidate> mline_0_candidates_;
178 std::vector<cricket::Candidate> mline_1_candidates_;
179 PeerConnectionInterface::IceConnectionState ice_connection_state_;
180 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
181};
182
183class WebRtcSessionForTest : public webrtc::WebRtcSession {
184 public:
185 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
186 talk_base::Thread* signaling_thread,
187 talk_base::Thread* worker_thread,
188 cricket::PortAllocator* port_allocator,
189 webrtc::IceObserver* ice_observer,
190 webrtc::MediaStreamSignaling* mediastream_signaling)
191 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
192 mediastream_signaling) {
193 RegisterIceObserver(ice_observer);
194 }
195 virtual ~WebRtcSessionForTest() {}
196
197 using cricket::BaseSession::GetTransportProxy;
198 using webrtc::WebRtcSession::SetAudioPlayout;
199 using webrtc::WebRtcSession::SetAudioSend;
200 using webrtc::WebRtcSession::SetCaptureDevice;
201 using webrtc::WebRtcSession::SetVideoPlayout;
202 using webrtc::WebRtcSession::SetVideoSend;
203};
204
wu@webrtc.org91053e72013-08-10 07:18:04 +0000205class WebRtcSessionCreateSDPObserverForTest
206 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000208 enum State {
209 kInit,
210 kFailed,
211 kSucceeded,
212 };
213 WebRtcSessionCreateSDPObserverForTest()
214 : description_(NULL), state_(kInit) {}
215
216 // CreateSessionDescriptionObserver implementation.
217 virtual void OnSuccess(SessionDescriptionInterface* desc) {
218 description_ = desc;
219 state_ = kSucceeded;
220 }
221 virtual void OnFailure(const std::string& error) {
222 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223 }
224
wu@webrtc.org91053e72013-08-10 07:18:04 +0000225 SessionDescriptionInterface* description() { return description_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226
wu@webrtc.org91053e72013-08-10 07:18:04 +0000227 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000228
wu@webrtc.org91053e72013-08-10 07:18:04 +0000229 protected:
230 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231
232 private:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000233 SessionDescriptionInterface* description_;
234 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000235};
236
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000237class FakeAudioRenderer : public cricket::AudioRenderer {
238 public:
239 FakeAudioRenderer() : channel_id_(-1) {}
240
241 virtual void AddChannel(int channel_id) OVERRIDE {
242 ASSERT(channel_id_ == -1);
243 channel_id_ = channel_id;
244 }
245 virtual void RemoveChannel(int channel_id) OVERRIDE {
246 ASSERT(channel_id == channel_id_);
247 channel_id_ = -1;
248 }
249
250 int channel_id() const { return channel_id_; }
251 private:
252 int channel_id_;
253};
254
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000255class WebRtcSessionTest : public testing::Test {
256 protected:
257 // TODO Investigate why ChannelManager crashes, if it's created
258 // after stun_server.
259 WebRtcSessionTest()
260 : media_engine_(new cricket::FakeMediaEngine()),
261 data_engine_(new cricket::FakeDataEngine()),
262 device_manager_(new cricket::FakeDeviceManager()),
263 channel_manager_(new cricket::ChannelManager(
264 media_engine_, data_engine_, device_manager_,
265 new cricket::CaptureManager(), talk_base::Thread::Current())),
266 tdesc_factory_(new cricket::TransportDescriptionFactory()),
267 desc_factory_(new cricket::MediaSessionDescriptionFactory(
268 channel_manager_.get(), tdesc_factory_.get())),
269 pss_(new talk_base::PhysicalSocketServer),
270 vss_(new talk_base::VirtualSocketServer(pss_.get())),
271 fss_(new talk_base::FirewallSocketServer(vss_.get())),
272 ss_scope_(fss_.get()),
273 stun_server_(talk_base::Thread::Current(), kStunAddr),
274 allocator_(&network_manager_, kStunAddr,
275 SocketAddress(), SocketAddress(), SocketAddress()) {
276 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
277 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
278 cricket::PORTALLOCATOR_DISABLE_RELAY |
279 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
280 EXPECT_TRUE(channel_manager_->Init());
281 desc_factory_->set_add_legacy_streams(false);
282 }
283
284 void AddInterface(const SocketAddress& addr) {
285 network_manager_.AddInterface(addr);
286 }
287
wu@webrtc.org91053e72013-08-10 07:18:04 +0000288 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 ASSERT_TRUE(session_.get() == NULL);
290 session_.reset(new WebRtcSessionForTest(
291 channel_manager_.get(), talk_base::Thread::Current(),
292 talk_base::Thread::Current(), &allocator_,
293 &observer_,
294 &mediastream_signaling_));
295
296 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
297 observer_.ice_connection_state_);
298 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
299 observer_.ice_gathering_state_);
300
wu@webrtc.org91053e72013-08-10 07:18:04 +0000301 EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000302 }
303
304 void InitWithDtmfCodec() {
305 // Add kTelephoneEventCodec for dtmf test.
306 std::vector<cricket::AudioCodec> codecs;
307 codecs.push_back(kTelephoneEventCodec);
308 media_engine_->SetAudioCodecs(codecs);
309 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000310 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 }
312
313 void InitWithDtls() {
314 constraints_.reset(new FakeConstraints());
315 constraints_->AddOptional(
316 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
317
wu@webrtc.org91053e72013-08-10 07:18:04 +0000318 Init(NULL);
319 }
320
321 void InitWithAsyncDtls(bool identity_request_should_fail) {
322 constraints_.reset(new FakeConstraints());
323 constraints_->AddOptional(
324 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
325 FakeIdentityService* identity_service = new FakeIdentityService();
326 identity_service->set_should_fail(identity_request_should_fail);
327 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 }
329
330 // Creates a local offer and applies it. Starts ice.
331 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
332 // to decide which streams to create.
333 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000334 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 SetLocalDescriptionWithoutError(offer);
336 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
337 observer_.ice_gathering_state_,
338 kIceCandidatesTimeout);
339 }
340
wu@webrtc.org91053e72013-08-10 07:18:04 +0000341 SessionDescriptionInterface* CreateOffer(
342 const webrtc::MediaConstraintsInterface* constraints) {
343 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
344 observer = new WebRtcSessionCreateSDPObserverForTest();
345 session_->CreateOffer(observer, constraints);
346 EXPECT_TRUE_WAIT(
347 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
348 1000);
349 return observer->description();
350 }
351
352 SessionDescriptionInterface* CreateAnswer(
353 const webrtc::MediaConstraintsInterface* constraints) {
354 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
355 = new WebRtcSessionCreateSDPObserverForTest();
356 session_->CreateAnswer(observer, constraints);
357 EXPECT_TRUE_WAIT(
358 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
359 1000);
360 return observer->description();
361 }
362
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000363 bool ChannelsExist() {
364 return (session_->voice_channel() != NULL &&
365 session_->video_channel() != NULL);
366 }
367
368 void CheckTransportChannels() {
369 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
370 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
371 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
372 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
373 }
374
375 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
376 ASSERT_TRUE(session_.get() != NULL);
377 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
378 ASSERT_TRUE(content != NULL);
379 const cricket::AudioContentDescription* audio_content =
380 static_cast<const cricket::AudioContentDescription*>(
381 content->description);
382 ASSERT_TRUE(audio_content != NULL);
383 ASSERT_EQ(1U, audio_content->cryptos().size());
384 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
385 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
386 audio_content->cryptos()[0].cipher_suite);
387 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
388 audio_content->protocol());
389
390 content = cricket::GetFirstVideoContent(sdp);
391 ASSERT_TRUE(content != NULL);
392 const cricket::VideoContentDescription* video_content =
393 static_cast<const cricket::VideoContentDescription*>(
394 content->description);
395 ASSERT_TRUE(video_content != NULL);
396 ASSERT_EQ(1U, video_content->cryptos().size());
397 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
398 video_content->cryptos()[0].cipher_suite);
399 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
400 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
401 video_content->protocol());
402 }
403
404 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
405 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
406 ASSERT_TRUE(content != NULL);
407 const cricket::AudioContentDescription* audio_content =
408 static_cast<const cricket::AudioContentDescription*>(
409 content->description);
410 ASSERT_TRUE(audio_content != NULL);
411 ASSERT_EQ(0U, audio_content->cryptos().size());
412
413 content = cricket::GetFirstVideoContent(sdp);
414 ASSERT_TRUE(content != NULL);
415 const cricket::VideoContentDescription* video_content =
416 static_cast<const cricket::VideoContentDescription*>(
417 content->description);
418 ASSERT_TRUE(video_content != NULL);
419 ASSERT_EQ(0U, video_content->cryptos().size());
420
421 if (dtls) {
422 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
423 audio_content->protocol());
424 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
425 video_content->protocol());
426 } else {
427 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
428 audio_content->protocol());
429 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
430 video_content->protocol());
431 }
432 }
433
434 // Set the internal fake description factories to do DTLS-SRTP.
435 void SetFactoryDtlsSrtp() {
436 desc_factory_->set_secure(cricket::SEC_ENABLED);
437 std::string identity_name = "WebRTC" +
438 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000439 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
440 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000441 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
442 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
443 }
444
445 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
446 bool expected) {
447 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
448 ASSERT_TRUE(audio != NULL);
449 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
450 if (expected) {
451 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
452 identity_fingerprint->algorithm);
453 }
454 const TransportInfo* video = sdp->GetTransportInfoByName("video");
455 ASSERT_TRUE(video != NULL);
456 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
457 if (expected) {
458 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
459 identity_fingerprint->algorithm);
460 }
461 }
462
463 void VerifyAnswerFromNonCryptoOffer() {
464 // Create a SDP without Crypto.
465 cricket::MediaSessionOptions options;
466 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000467 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000469 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000470 VerifyNoCryptoParams(offer->description(), false);
471 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
wu@webrtc.org91053e72013-08-10 07:18:04 +0000472 offer);
473 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 // Answer should be NULL as no crypto params in offer.
475 ASSERT_TRUE(answer == NULL);
476 }
477
478 void VerifyAnswerFromCryptoOffer() {
479 cricket::MediaSessionOptions options;
480 options.has_video = true;
481 options.bundle_enabled = true;
482 scoped_ptr<JsepSessionDescription> offer(
483 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
484 ASSERT_TRUE(offer.get() != NULL);
485 VerifyCryptoParams(offer->description());
486 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000487 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 ASSERT_TRUE(answer.get() != NULL);
489 VerifyCryptoParams(answer->description());
490 }
491
492 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
493 const cricket::SessionDescription* desc2,
494 bool expect_equal) {
495 if (desc1->contents().size() != desc2->contents().size()) {
496 EXPECT_FALSE(expect_equal);
497 return;
498 }
499
500 const cricket::ContentInfos& contents = desc1->contents();
501 cricket::ContentInfos::const_iterator it = contents.begin();
502
503 for (; it != contents.end(); ++it) {
504 const cricket::TransportDescription* transport_desc1 =
505 desc1->GetTransportDescriptionByName(it->name);
506 const cricket::TransportDescription* transport_desc2 =
507 desc2->GetTransportDescriptionByName(it->name);
508 if (!transport_desc1 || !transport_desc2) {
509 EXPECT_FALSE(expect_equal);
510 return;
511 }
512 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
513 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
514 EXPECT_FALSE(expect_equal);
515 return;
516 }
517 }
518 EXPECT_TRUE(expect_equal);
519 }
520 // Creates a remote offer and and applies it as a remote description,
521 // creates a local answer and applies is as a local description.
522 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
523 // to decide which local and remote streams to create.
524 void CreateAndSetRemoteOfferAndLocalAnswer() {
525 SessionDescriptionInterface* offer = CreateRemoteOffer();
526 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000527 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 SetLocalDescriptionWithoutError(answer);
529 }
530 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
531 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
532 }
533 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
534 BaseSession::State expected_state) {
535 SetLocalDescriptionWithoutError(desc);
536 EXPECT_EQ(expected_state, session_->state());
537 }
538 void SetLocalDescriptionExpectError(const std::string& expected_error,
539 SessionDescriptionInterface* desc) {
540 std::string error;
541 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
542 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
543 EXPECT_NE(std::string::npos, error.find(expected_error));
544 }
545 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
546 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
547 }
548 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
549 BaseSession::State expected_state) {
550 SetRemoteDescriptionWithoutError(desc);
551 EXPECT_EQ(expected_state, session_->state());
552 }
553 void SetRemoteDescriptionExpectError(const std::string& expected_error,
554 SessionDescriptionInterface* desc) {
555 std::string error;
556 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
557 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
558 EXPECT_NE(std::string::npos, error.find(expected_error));
559 }
560
561 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
562 SessionDescriptionInterface** nocrypto_answer) {
563 // Create a SDP without Crypto.
564 cricket::MediaSessionOptions options;
565 options.has_video = true;
566 options.bundle_enabled = true;
567 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
568 ASSERT_TRUE(*offer != NULL);
569 VerifyCryptoParams((*offer)->description());
570
571 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
572 cricket::SEC_DISABLED);
573 EXPECT_TRUE(*nocrypto_answer != NULL);
574 }
575
576 JsepSessionDescription* CreateRemoteOfferWithVersion(
577 cricket::MediaSessionOptions options,
578 cricket::SecurePolicy secure_policy,
579 const std::string& session_version,
580 const SessionDescriptionInterface* current_desc) {
581 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
582 const cricket::SessionDescription* cricket_desc = NULL;
583 if (current_desc) {
584 cricket_desc = current_desc->description();
585 session_id = current_desc->session_id();
586 }
587
588 desc_factory_->set_secure(secure_policy);
589 JsepSessionDescription* offer(
590 new JsepSessionDescription(JsepSessionDescription::kOffer));
591 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
592 session_id, session_version)) {
593 delete offer;
594 offer = NULL;
595 }
596 return offer;
597 }
598 JsepSessionDescription* CreateRemoteOffer(
599 cricket::MediaSessionOptions options) {
600 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
601 kSessionVersion, NULL);
602 }
603 JsepSessionDescription* CreateRemoteOffer(
604 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
605 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
606 }
607 JsepSessionDescription* CreateRemoteOffer(
608 cricket::MediaSessionOptions options,
609 const SessionDescriptionInterface* current_desc) {
610 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
611 kSessionVersion, current_desc);
612 }
613
614 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
615 // before this function to decide which streams to create.
616 JsepSessionDescription* CreateRemoteOffer() {
617 cricket::MediaSessionOptions options;
618 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
619 return CreateRemoteOffer(options, session_->remote_description());
620 }
621
622 JsepSessionDescription* CreateRemoteAnswer(
623 const SessionDescriptionInterface* offer,
624 cricket::MediaSessionOptions options,
625 cricket::SecurePolicy policy) {
626 desc_factory_->set_secure(policy);
627 const std::string session_id =
628 talk_base::ToString(talk_base::CreateRandomId64());
629 JsepSessionDescription* answer(
630 new JsepSessionDescription(JsepSessionDescription::kAnswer));
631 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
632 options, NULL),
633 session_id, kSessionVersion)) {
634 delete answer;
635 answer = NULL;
636 }
637 return answer;
638 }
639
640 JsepSessionDescription* CreateRemoteAnswer(
641 const SessionDescriptionInterface* offer,
642 cricket::MediaSessionOptions options) {
643 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
644 }
645
646 // Creates an answer session description with streams based on
647 // |mediastream_signaling_|. Call
648 // mediastream_signaling_.UseOptionsWithStreamX() before this function
649 // to decide which streams to create.
650 JsepSessionDescription* CreateRemoteAnswer(
651 const SessionDescriptionInterface* offer) {
652 cricket::MediaSessionOptions options;
653 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
654 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
655 }
656
657 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
658 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000659 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000660 mediastream_signaling_.SendAudioVideoStream1();
661 FakeConstraints constraints;
662 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000663 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000664 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
665 // and answer.
666 SetLocalDescriptionWithoutError(offer);
667
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000668 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
669 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000670 std::string sdp;
671 EXPECT_TRUE(answer->ToString(&sdp));
672
673 size_t expected_candidate_num = 2;
674 if (!rtcp_mux) {
675 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
676 // for rtp and rtcp.
677 expected_candidate_num = 4;
678 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 const std::string kRtcpMux = "a=rtcp-mux";
680 const std::string kXRtcpMux = "a=xrtcp-mux";
681 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
682 kXRtcpMux.c_str(), kXRtcpMux.length(),
683 &sdp);
684 }
685
686 SessionDescriptionInterface* new_answer = CreateSessionDescription(
687 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688
689 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000690 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
692 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
693 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
694 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
695 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
696 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
697 if (bundle) {
698 EXPECT_TRUE(c0.IsEquivalent(c1));
699 } else {
700 EXPECT_FALSE(c0.IsEquivalent(c1));
701 }
702 }
703 }
704 // Tests that we can only send DTMF when the dtmf codec is supported.
705 void TestCanInsertDtmf(bool can) {
706 if (can) {
707 InitWithDtmfCodec();
708 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000709 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000710 }
711 mediastream_signaling_.SendAudioVideoStream1();
712 CreateAndSetRemoteOfferAndLocalAnswer();
713 EXPECT_FALSE(session_->CanInsertDtmf(""));
714 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
715 }
716
717 // The method sets up a call from the session to itself, in a loopback
718 // arrangement. It also uses a firewall rule to create a temporary
719 // disconnection. This code is placed as a method so that it can be invoked
720 // by multiple tests with different allocators (e.g. with and without BUNDLE).
721 // While running the call, this method also checks if the session goes through
722 // the correct sequence of ICE states when a connection is established,
723 // broken, and re-established.
724 // The Connection state should go:
725 // New -> Checking -> Connected -> Disconnected -> Connected.
726 // The Gathering state should go: New -> Gathering -> Completed.
727 void TestLoopbackCall() {
728 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000729 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000731 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000732
733 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
734 observer_.ice_gathering_state_);
735 SetLocalDescriptionWithoutError(offer);
736 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
737 observer_.ice_connection_state_);
738 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
739 observer_.ice_gathering_state_,
740 kIceCandidatesTimeout);
741 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
742 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
743 observer_.ice_gathering_state_,
744 kIceCandidatesTimeout);
745
746 std::string sdp;
747 offer->ToString(&sdp);
748 SessionDescriptionInterface* desc =
749 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
750 ASSERT_TRUE(desc != NULL);
751 SetRemoteDescriptionWithoutError(desc);
752
753 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
754 observer_.ice_connection_state_,
755 kIceCandidatesTimeout);
756 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
757 observer_.ice_connection_state_,
758 kIceCandidatesTimeout);
759 // TODO(bemasc): EXPECT(Completed) once the details are standardized.
760
761 // Adding firewall rule to block ping requests, which should cause
762 // transport channel failure.
763 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
764 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
765 observer_.ice_connection_state_,
766 kIceCandidatesTimeout);
767
768 // Clearing the rules, session should move back to completed state.
769 fss_->ClearRules();
770 // Session is automatically calling OnSignalingReady after creation of
771 // new portallocator session which will allocate new set of candidates.
772
773 // TODO(bemasc): Change this to Completed once the details are standardized.
774 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
775 observer_.ice_connection_state_,
776 kIceCandidatesTimeout);
777 }
778
779 void VerifyTransportType(const std::string& content_name,
780 cricket::TransportProtocol protocol) {
781 const cricket::Transport* transport = session_->GetTransport(content_name);
782 ASSERT_TRUE(transport != NULL);
783 EXPECT_EQ(protocol, transport->protocol());
784 }
785
786 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
787 void AddCNCodecs() {
788 // Add kTelephoneEventCodec for dtmf test.
789 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
790 codecs.push_back(kCNCodec1);
791 codecs.push_back(kCNCodec2);
792 media_engine_->SetAudioCodecs(codecs);
793 desc_factory_->set_audio_codecs(codecs);
794 }
795
796 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
797 const cricket::ContentDescription* description = content->description;
798 ASSERT(description != NULL);
799 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000800 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000801 ASSERT(audio_content_desc != NULL);
802 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
803 if (audio_content_desc->codecs()[i].name == "CN")
804 return false;
805 }
806 return true;
807 }
808
809 void SetLocalDescriptionWithDataChannel() {
810 webrtc::DataChannelInit dci;
811 dci.reliable = false;
812 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000813 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000814 SetLocalDescriptionWithoutError(offer);
815 }
816
wu@webrtc.org91053e72013-08-10 07:18:04 +0000817 void VerifyMultipleAsyncCreateDescription(
818 bool success, CreateSessionDescriptionRequest::Type type) {
819 InitWithAsyncDtls(!success);
820
821 if (type == CreateSessionDescriptionRequest::kAnswer) {
822 cricket::MediaSessionOptions options;
823 scoped_ptr<JsepSessionDescription> offer(
824 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
825 ASSERT_TRUE(offer.get() != NULL);
826 SetRemoteDescriptionWithoutError(offer.release());
827 }
828
829 const int kNumber = 3;
830 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
831 observers[kNumber];
832 for (int i = 0; i < kNumber; ++i) {
833 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
834 if (type == CreateSessionDescriptionRequest::kOffer) {
835 session_->CreateOffer(observers[i], NULL);
836 } else {
837 session_->CreateAnswer(observers[i], NULL);
838 }
839 }
840
841 WebRtcSessionCreateSDPObserverForTest::State expected_state =
842 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
843 WebRtcSessionCreateSDPObserverForTest::kFailed;
844
845 for (int i = 0; i < kNumber; ++i) {
846 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
847 if (success) {
848 EXPECT_TRUE(observers[i]->description() != NULL);
849 } else {
850 EXPECT_TRUE(observers[i]->description() == NULL);
851 }
852 }
853 }
854
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855 cricket::FakeMediaEngine* media_engine_;
856 cricket::FakeDataEngine* data_engine_;
857 cricket::FakeDeviceManager* device_manager_;
858 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
859 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000860 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000861 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
862 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
863 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
864 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
865 talk_base::SocketServerScope ss_scope_;
866 cricket::TestStunServer stun_server_;
867 talk_base::FakeNetworkManager network_manager_;
868 cricket::BasicPortAllocator allocator_;
869 talk_base::scoped_ptr<FakeConstraints> constraints_;
870 FakeMediaStreamSignaling mediastream_signaling_;
871 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
872 MockIceObserver observer_;
873 cricket::FakeVideoMediaChannel* video_channel_;
874 cricket::FakeVoiceMediaChannel* voice_channel_;
875};
876
877TEST_F(WebRtcSessionTest, TestInitialize) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000878 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000879}
880
881TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
882 InitWithDtls();
883}
884
wu@webrtc.org91053e72013-08-10 07:18:04 +0000885// Verifies that WebRtcSession uses SEC_REQUIRED by default.
886TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
887 Init(NULL);
888 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
889}
890
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000891TEST_F(WebRtcSessionTest, TestSessionCandidates) {
892 TestSessionCandidatesWithBundleRtcpMux(false, false);
893}
894
895// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
896// with rtcp-mux and/or bundle.
897TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
898 TestSessionCandidatesWithBundleRtcpMux(false, true);
899}
900
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
902 TestSessionCandidatesWithBundleRtcpMux(true, true);
903}
904
905TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
906 AddInterface(kClientAddr1);
907 AddInterface(kClientAddr2);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000908 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000909 mediastream_signaling_.SendAudioVideoStream1();
910 InitiateCall();
911 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
912 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
913 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
914}
915
916TEST_F(WebRtcSessionTest, TestStunError) {
917 AddInterface(kClientAddr1);
918 AddInterface(kClientAddr2);
919 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000920 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000921 mediastream_signaling_.SendAudioVideoStream1();
922 InitiateCall();
923 // Since kClientAddr1 is blocked, not expecting stun candidates for it.
924 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
925 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
926 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
927}
928
929// Test creating offers and receive answers and make sure the
930// media engine creates the expected send and receive streams.
931TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000932 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000934 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 const std::string session_id_orig = offer->session_id();
936 const std::string session_version_orig = offer->session_version();
937 SetLocalDescriptionWithoutError(offer);
938
939 mediastream_signaling_.SendAudioVideoStream2();
940 SessionDescriptionInterface* answer =
941 CreateRemoteAnswer(session_->local_description());
942 SetRemoteDescriptionWithoutError(answer);
943
944 video_channel_ = media_engine_->GetVideoChannel(0);
945 voice_channel_ = media_engine_->GetVoiceChannel(0);
946
947 ASSERT_EQ(1u, video_channel_->recv_streams().size());
948 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
949
950 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
951 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
952
953 ASSERT_EQ(1u, video_channel_->send_streams().size());
954 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
955 ASSERT_EQ(1u, voice_channel_->send_streams().size());
956 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
957
958 // Create new offer without send streams.
959 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000960 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000961
962 // Verify the session id is the same and the session version is
963 // increased.
964 EXPECT_EQ(session_id_orig, offer->session_id());
965 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
966 talk_base::FromString<uint64>(offer->session_version()));
967
968 SetLocalDescriptionWithoutError(offer);
969
970 mediastream_signaling_.SendAudioVideoStream2();
971 answer = CreateRemoteAnswer(session_->local_description());
972 SetRemoteDescriptionWithoutError(answer);
973
974 EXPECT_EQ(0u, video_channel_->send_streams().size());
975 EXPECT_EQ(0u, voice_channel_->send_streams().size());
976
977 // Make sure the receive streams have not changed.
978 ASSERT_EQ(1u, video_channel_->recv_streams().size());
979 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
980 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
981 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
982}
983
984// Test receiving offers and creating answers and make sure the
985// media engine creates the expected send and receive streams.
986TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000987 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000989 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000990 SetRemoteDescriptionWithoutError(offer);
991
992 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000993 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 SetLocalDescriptionWithoutError(answer);
995
996 const std::string session_id_orig = answer->session_id();
997 const std::string session_version_orig = answer->session_version();
998
999 video_channel_ = media_engine_->GetVideoChannel(0);
1000 voice_channel_ = media_engine_->GetVoiceChannel(0);
1001
1002 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1003 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1004
1005 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1006 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1007
1008 ASSERT_EQ(1u, video_channel_->send_streams().size());
1009 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1010 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1011 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1012
1013 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001014 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001015 SetRemoteDescriptionWithoutError(offer);
1016
1017 // Answer by turning off all send streams.
1018 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001019 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001020
1021 // Verify the session id is the same and the session version is
1022 // increased.
1023 EXPECT_EQ(session_id_orig, answer->session_id());
1024 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1025 talk_base::FromString<uint64>(answer->session_version()));
1026 SetLocalDescriptionWithoutError(answer);
1027
1028 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1029 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1030 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1031 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1032 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1033 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1034
1035 // Make sure we have no send streams.
1036 EXPECT_EQ(0u, video_channel_->send_streams().size());
1037 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1038}
1039
1040// Test we will return fail when apply an offer that doesn't have
1041// crypto enabled.
1042TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001043 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001044 cricket::MediaSessionOptions options;
1045 options.has_video = true;
1046 JsepSessionDescription* offer = CreateRemoteOffer(
1047 options, cricket::SEC_DISABLED);
1048 ASSERT_TRUE(offer != NULL);
1049 VerifyNoCryptoParams(offer->description(), false);
1050 // SetRemoteDescription and SetLocalDescription will take the ownership of
1051 // the offer.
1052 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
1053 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1054 ASSERT_TRUE(offer != NULL);
1055 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
1056}
1057
1058// Test we will return fail when apply an answer that doesn't have
1059// crypto enabled.
1060TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001061 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001062 SessionDescriptionInterface* offer = NULL;
1063 SessionDescriptionInterface* answer = NULL;
1064 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1065 // SetRemoteDescription and SetLocalDescription will take the ownership of
1066 // the offer.
1067 SetRemoteDescriptionWithoutError(offer);
1068 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
1069}
1070
1071// Test we will return fail when apply an answer that doesn't have
1072// crypto enabled.
1073TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001074 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075 SessionDescriptionInterface* offer = NULL;
1076 SessionDescriptionInterface* answer = NULL;
1077 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1078 // SetRemoteDescription and SetLocalDescription will take the ownership of
1079 // the offer.
1080 SetLocalDescriptionWithoutError(offer);
1081 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
1082}
1083
1084// Test that we can create and set an offer with a DTLS fingerprint.
1085TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1086 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1087 InitWithDtls();
1088 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001089 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001090 ASSERT_TRUE(offer != NULL);
1091 VerifyFingerprintStatus(offer->description(), true);
1092 // SetLocalDescription will take the ownership of the offer.
1093 SetLocalDescriptionWithoutError(offer);
1094}
1095
1096// Test that we can process an offer with a DTLS fingerprint
1097// and that we return an answer with a fingerprint.
1098TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1099 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1100 InitWithDtls();
1101 SetFactoryDtlsSrtp();
1102 cricket::MediaSessionOptions options;
1103 options.has_video = true;
1104 JsepSessionDescription* offer = CreateRemoteOffer(options);
1105 ASSERT_TRUE(offer != NULL);
1106 VerifyFingerprintStatus(offer->description(), true);
1107
1108 // SetRemoteDescription will take the ownership of the offer.
1109 SetRemoteDescriptionWithoutError(offer);
1110
1111 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001112 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001113 ASSERT_TRUE(answer != NULL);
1114 VerifyFingerprintStatus(answer->description(), true);
1115 // Check that we don't have an a=crypto line in the answer.
1116 VerifyNoCryptoParams(answer->description(), true);
1117
1118 // Now set the local description, which should work, even without a=crypto.
1119 SetLocalDescriptionWithoutError(answer);
1120}
1121
1122// Test that even if we support DTLS, if the other side didn't offer a
1123// fingerprint, we don't either.
1124TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1125 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1126 InitWithDtls();
1127 cricket::MediaSessionOptions options;
1128 options.has_video = true;
1129 JsepSessionDescription* offer = CreateRemoteOffer(
1130 options, cricket::SEC_REQUIRED);
1131 ASSERT_TRUE(offer != NULL);
1132 VerifyFingerprintStatus(offer->description(), false);
1133
1134 // SetRemoteDescription will take the ownership of
1135 // the offer.
1136 SetRemoteDescriptionWithoutError(offer);
1137
1138 // Verify that we don't get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001139 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 ASSERT_TRUE(answer != NULL);
1141 VerifyFingerprintStatus(answer->description(), false);
1142
1143 // Now set the local description.
1144 SetLocalDescriptionWithoutError(answer);
1145}
1146
1147TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001148 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 mediastream_signaling_.SendNothing();
1150 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001151 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 SetLocalDescriptionWithoutError(offer);
1153
1154 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001155 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 SetLocalDescriptionWithoutError(offer2);
1157}
1158
1159TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001160 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 mediastream_signaling_.SendNothing();
1162 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001163 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 SetRemoteDescriptionWithoutError(offer);
1165
wu@webrtc.org91053e72013-08-10 07:18:04 +00001166 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167 SetRemoteDescriptionWithoutError(offer2);
1168}
1169
1170TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001171 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001173 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001175 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001176 SetRemoteDescriptionExpectError(
1177 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
1178 offer);
1179}
1180
1181TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001182 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001183 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001184 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001186 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 SetLocalDescriptionExpectError(
1188 "Called with type in wrong state, type: "
1189 "offer state: STATE_RECEIVEDINITIATE",
1190 offer);
1191}
1192
1193TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001194 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195 mediastream_signaling_.SendNothing();
1196 SessionDescriptionInterface* offer = CreateRemoteOffer();
1197 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1198
1199 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001200 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001201 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1202 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1203
1204 mediastream_signaling_.SendAudioVideoStream1();
1205 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001206 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001207 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1208
1209 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1210
1211 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001212 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1214}
1215
1216TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001217 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001219 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001220 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1221
1222 JsepSessionDescription* pranswer =
1223 CreateRemoteAnswer(session_->local_description());
1224 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1225
1226 SetRemoteDescriptionExpectState(pranswer,
1227 BaseSession::STATE_RECEIVEDPRACCEPT);
1228
1229 mediastream_signaling_.SendAudioVideoStream1();
1230 JsepSessionDescription* pranswer2 =
1231 CreateRemoteAnswer(session_->local_description());
1232 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1233
1234 SetRemoteDescriptionExpectState(pranswer2,
1235 BaseSession::STATE_RECEIVEDPRACCEPT);
1236
1237 mediastream_signaling_.SendAudioVideoStream2();
1238 SessionDescriptionInterface* answer =
1239 CreateRemoteAnswer(session_->local_description());
1240 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1241}
1242
1243TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001244 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001245 mediastream_signaling_.SendNothing();
1246 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001247 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 SessionDescriptionInterface* answer =
1249 CreateRemoteAnswer(offer.get());
1250 SetLocalDescriptionExpectError(
1251 "Called with type in wrong state, type: answer state: STATE_INIT",
1252 answer);
1253}
1254
1255TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001256 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001257 mediastream_signaling_.SendNothing();
1258 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001259 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 SessionDescriptionInterface* answer =
1261 CreateRemoteAnswer(offer.get());
1262 SetRemoteDescriptionExpectError(
1263 "Called with type in wrong state, type: answer state: STATE_INIT",
1264 answer);
1265}
1266
1267TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001268 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269 mediastream_signaling_.SendAudioVideoStream1();
1270
1271 cricket::Candidate candidate;
1272 candidate.set_component(1);
1273 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1274
1275 // Fail since we have not set a offer description.
1276 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1277
wu@webrtc.org91053e72013-08-10 07:18:04 +00001278 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001279 SetLocalDescriptionWithoutError(offer);
1280 // Candidate should be allowed to add before remote description.
1281 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1282 candidate.set_component(2);
1283 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1284 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1285
1286 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1287 session_->local_description());
1288 SetRemoteDescriptionWithoutError(answer);
1289
1290 // Verifying the candidates are copied properly from internal vector.
1291 const SessionDescriptionInterface* remote_desc =
1292 session_->remote_description();
1293 ASSERT_TRUE(remote_desc != NULL);
1294 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1295 const IceCandidateCollection* candidates =
1296 remote_desc->candidates(kMediaContentIndex0);
1297 ASSERT_EQ(2u, candidates->count());
1298 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1299 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1300 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1301 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1302
1303 candidate.set_component(2);
1304 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1305 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1306 ASSERT_EQ(3u, candidates->count());
1307
1308 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1309 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1310}
1311
1312// Test that a remote candidate is added to the remote session description and
1313// that it is retained if the remote session description is changed.
1314TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001315 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001316 cricket::Candidate candidate1;
1317 candidate1.set_component(1);
1318 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1319 candidate1);
1320 mediastream_signaling_.SendAudioVideoStream1();
1321 CreateAndSetRemoteOfferAndLocalAnswer();
1322
1323 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1324 const SessionDescriptionInterface* remote_desc =
1325 session_->remote_description();
1326 ASSERT_TRUE(remote_desc != NULL);
1327 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1328 const IceCandidateCollection* candidates =
1329 remote_desc->candidates(kMediaContentIndex0);
1330 ASSERT_EQ(1u, candidates->count());
1331 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1332
1333 // Update the RemoteSessionDescription with a new session description and
1334 // a candidate and check that the new remote session description contains both
1335 // candidates.
1336 SessionDescriptionInterface* offer = CreateRemoteOffer();
1337 cricket::Candidate candidate2;
1338 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1339 candidate2);
1340 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1341 SetRemoteDescriptionWithoutError(offer);
1342
1343 remote_desc = session_->remote_description();
1344 ASSERT_TRUE(remote_desc != NULL);
1345 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1346 candidates = remote_desc->candidates(kMediaContentIndex0);
1347 ASSERT_EQ(2u, candidates->count());
1348 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1349 // Username and password have be updated with the TransportInfo of the
1350 // SessionDescription, won't be equal to the original one.
1351 candidate2.set_username(candidates->at(0)->candidate().username());
1352 candidate2.set_password(candidates->at(0)->candidate().password());
1353 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1354 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1355 // No need to verify the username and password.
1356 candidate1.set_username(candidates->at(1)->candidate().username());
1357 candidate1.set_password(candidates->at(1)->candidate().password());
1358 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1359
1360 // Test that the candidate is ignored if we can add the same candidate again.
1361 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1362}
1363
1364// Test that local candidates are added to the local session description and
1365// that they are retained if the local session description is changed.
1366TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1367 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001368 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369 mediastream_signaling_.SendAudioVideoStream1();
1370 CreateAndSetRemoteOfferAndLocalAnswer();
1371
1372 const SessionDescriptionInterface* local_desc = session_->local_description();
1373 const IceCandidateCollection* candidates =
1374 local_desc->candidates(kMediaContentIndex0);
1375 ASSERT_TRUE(candidates != NULL);
1376 EXPECT_EQ(0u, candidates->count());
1377
1378 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1379
1380 local_desc = session_->local_description();
1381 candidates = local_desc->candidates(kMediaContentIndex0);
1382 ASSERT_TRUE(candidates != NULL);
1383 EXPECT_LT(0u, candidates->count());
1384 candidates = local_desc->candidates(1);
1385 ASSERT_TRUE(candidates != NULL);
1386 EXPECT_LT(0u, candidates->count());
1387
1388 // Update the session descriptions.
1389 mediastream_signaling_.SendAudioVideoStream1();
1390 CreateAndSetRemoteOfferAndLocalAnswer();
1391
1392 local_desc = session_->local_description();
1393 candidates = local_desc->candidates(kMediaContentIndex0);
1394 ASSERT_TRUE(candidates != NULL);
1395 EXPECT_LT(0u, candidates->count());
1396 candidates = local_desc->candidates(1);
1397 ASSERT_TRUE(candidates != NULL);
1398 EXPECT_LT(0u, candidates->count());
1399}
1400
1401// Test that we can set a remote session description with remote candidates.
1402TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001403 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001404
1405 cricket::Candidate candidate1;
1406 candidate1.set_component(1);
1407 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1408 candidate1);
1409 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001410 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411
1412 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1413 SetRemoteDescriptionWithoutError(offer);
1414
1415 const SessionDescriptionInterface* remote_desc =
1416 session_->remote_description();
1417 ASSERT_TRUE(remote_desc != NULL);
1418 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1419 const IceCandidateCollection* candidates =
1420 remote_desc->candidates(kMediaContentIndex0);
1421 ASSERT_EQ(1u, candidates->count());
1422 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1423
wu@webrtc.org91053e72013-08-10 07:18:04 +00001424 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001425 SetLocalDescriptionWithoutError(answer);
1426}
1427
1428// Test that offers and answers contains ice candidates when Ice candidates have
1429// been gathered.
1430TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1431 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001432 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001433 mediastream_signaling_.SendAudioVideoStream1();
1434 // Ice is started but candidates are not provided until SetLocalDescription
1435 // is called.
1436 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1437 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1438 CreateAndSetRemoteOfferAndLocalAnswer();
1439 // Wait until at least one local candidate has been collected.
1440 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1441 kIceCandidatesTimeout);
1442 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1443 kIceCandidatesTimeout);
1444
1445 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001446 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001447 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1448 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1449 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1450 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1451
1452 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1453 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001454 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001455 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1456 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1457 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1458 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1459 SetLocalDescriptionWithoutError(answer);
1460}
1461
1462// Verifies TransportProxy and media channels are created with content names
1463// present in the SessionDescription.
1464TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001465 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001466 mediastream_signaling_.SendAudioVideoStream1();
1467 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001468 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469
1470 // CreateOffer creates session description with the content names "audio" and
1471 // "video". Goal is to modify these content names and verify transport channel
1472 // proxy in the BaseSession, as proxies are created with the content names
1473 // present in SDP.
1474 std::string sdp;
1475 EXPECT_TRUE(offer->ToString(&sdp));
1476 const std::string kAudioMid = "a=mid:audio";
1477 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1478 const std::string kVideoMid = "a=mid:video";
1479 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1480
1481 // Replacing |audio| with |audio_content_name|.
1482 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1483 kAudioMidReplaceStr.c_str(),
1484 kAudioMidReplaceStr.length(),
1485 &sdp);
1486 // Replacing |video| with |video_content_name|.
1487 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1488 kVideoMidReplaceStr.c_str(),
1489 kVideoMidReplaceStr.length(),
1490 &sdp);
1491
1492 SessionDescriptionInterface* modified_offer =
1493 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1494
1495 SetRemoteDescriptionWithoutError(modified_offer);
1496
1497 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001498 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001499 SetLocalDescriptionWithoutError(answer);
1500
1501 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1502 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1503 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1504 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1505}
1506
1507// Test that an offer contains the correct media content descriptions based on
1508// the send streams when no constraints have been set.
1509TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001510 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001512 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 ASSERT_TRUE(offer != NULL);
1514 const cricket::ContentInfo* content =
1515 cricket::GetFirstAudioContent(offer->description());
1516 EXPECT_TRUE(content != NULL);
1517 content = cricket::GetFirstVideoContent(offer->description());
1518 EXPECT_TRUE(content == NULL);
1519}
1520
1521// Test that an offer contains the correct media content descriptions based on
1522// the send streams when no constraints have been set.
1523TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001524 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 // Test Audio only offer.
1526 mediastream_signaling_.UseOptionsAudioOnly();
1527 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001528 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001529 const cricket::ContentInfo* content =
1530 cricket::GetFirstAudioContent(offer->description());
1531 EXPECT_TRUE(content != NULL);
1532 content = cricket::GetFirstVideoContent(offer->description());
1533 EXPECT_TRUE(content == NULL);
1534
1535 // Test Audio / Video offer.
1536 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001537 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001538 content = cricket::GetFirstAudioContent(offer->description());
1539 EXPECT_TRUE(content != NULL);
1540 content = cricket::GetFirstVideoContent(offer->description());
1541 EXPECT_TRUE(content != NULL);
1542}
1543
1544// Test that an offer contains no media content descriptions if
1545// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1546TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001547 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001548 webrtc::FakeConstraints constraints_no_receive;
1549 constraints_no_receive.SetMandatoryReceiveAudio(false);
1550 constraints_no_receive.SetMandatoryReceiveVideo(false);
1551
1552 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001553 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001554 ASSERT_TRUE(offer != NULL);
1555 const cricket::ContentInfo* content =
1556 cricket::GetFirstAudioContent(offer->description());
1557 EXPECT_TRUE(content == NULL);
1558 content = cricket::GetFirstVideoContent(offer->description());
1559 EXPECT_TRUE(content == NULL);
1560}
1561
1562// Test that an offer contains only audio media content descriptions if
1563// kOfferToReceiveAudio constraints are set to true.
1564TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001565 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 webrtc::FakeConstraints constraints_audio_only;
1567 constraints_audio_only.SetMandatoryReceiveAudio(true);
1568 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001569 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001570
1571 const cricket::ContentInfo* content =
1572 cricket::GetFirstAudioContent(offer->description());
1573 EXPECT_TRUE(content != NULL);
1574 content = cricket::GetFirstVideoContent(offer->description());
1575 EXPECT_TRUE(content == NULL);
1576}
1577
1578// Test that an offer contains audio and video media content descriptions if
1579// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1580TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001581 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582 // Test Audio / Video offer.
1583 webrtc::FakeConstraints constraints_audio_video;
1584 constraints_audio_video.SetMandatoryReceiveAudio(true);
1585 constraints_audio_video.SetMandatoryReceiveVideo(true);
1586 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001587 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 const cricket::ContentInfo* content =
1589 cricket::GetFirstAudioContent(offer->description());
1590
1591 EXPECT_TRUE(content != NULL);
1592 content = cricket::GetFirstVideoContent(offer->description());
1593 EXPECT_TRUE(content != NULL);
1594
1595 // TODO(perkj): Should the direction be set to SEND_ONLY if
1596 // The constraints is set to not receive audio or video but a track is added?
1597}
1598
1599// Test that an answer can not be created if the last remote description is not
1600// an offer.
1601TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001602 Init(NULL);
1603 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604 SetLocalDescriptionWithoutError(offer);
1605 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1606 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001607 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608}
1609
1610// Test that an answer contains the correct media content descriptions when no
1611// constraints have been set.
1612TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001613 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001614 // Create a remote offer with audio and video content.
1615 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1616 SetRemoteDescriptionWithoutError(offer.release());
1617 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001618 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 const cricket::ContentInfo* content =
1620 cricket::GetFirstAudioContent(answer->description());
1621 ASSERT_TRUE(content != NULL);
1622 EXPECT_FALSE(content->rejected);
1623
1624 content = cricket::GetFirstVideoContent(answer->description());
1625 ASSERT_TRUE(content != NULL);
1626 EXPECT_FALSE(content->rejected);
1627}
1628
1629// Test that an answer contains the correct media content descriptions when no
1630// constraints have been set and the offer only contain audio.
1631TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001632 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633 // Create a remote offer with audio only.
1634 cricket::MediaSessionOptions options;
1635 options.has_audio = true;
1636 options.has_video = false;
1637 talk_base::scoped_ptr<JsepSessionDescription> offer(
1638 CreateRemoteOffer(options));
1639 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1640 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1641
1642 SetRemoteDescriptionWithoutError(offer.release());
1643 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001644 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645 const cricket::ContentInfo* content =
1646 cricket::GetFirstAudioContent(answer->description());
1647 ASSERT_TRUE(content != NULL);
1648 EXPECT_FALSE(content->rejected);
1649
1650 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1651}
1652
1653// Test that an answer contains the correct media content descriptions when no
1654// constraints have been set.
1655TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001656 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657 // Create a remote offer with audio and video content.
1658 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1659 SetRemoteDescriptionWithoutError(offer.release());
1660 // Test with a stream with tracks.
1661 mediastream_signaling_.SendAudioVideoStream1();
1662 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001663 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 const cricket::ContentInfo* content =
1665 cricket::GetFirstAudioContent(answer->description());
1666 ASSERT_TRUE(content != NULL);
1667 EXPECT_FALSE(content->rejected);
1668
1669 content = cricket::GetFirstVideoContent(answer->description());
1670 ASSERT_TRUE(content != NULL);
1671 EXPECT_FALSE(content->rejected);
1672}
1673
1674// Test that an answer contains the correct media content descriptions when
1675// constraints have been set but no stream is sent.
1676TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001677 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678 // Create a remote offer with audio and video content.
1679 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1680 SetRemoteDescriptionWithoutError(offer.release());
1681
1682 webrtc::FakeConstraints constraints_no_receive;
1683 constraints_no_receive.SetMandatoryReceiveAudio(false);
1684 constraints_no_receive.SetMandatoryReceiveVideo(false);
1685
1686 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001687 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 const cricket::ContentInfo* content =
1689 cricket::GetFirstAudioContent(answer->description());
1690 ASSERT_TRUE(content != NULL);
1691 EXPECT_TRUE(content->rejected);
1692
1693 content = cricket::GetFirstVideoContent(answer->description());
1694 ASSERT_TRUE(content != NULL);
1695 EXPECT_TRUE(content->rejected);
1696}
1697
1698// Test that an answer contains the correct media content descriptions when
1699// constraints have been set and streams are sent.
1700TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001701 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001702 // Create a remote offer with audio and video content.
1703 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1704 SetRemoteDescriptionWithoutError(offer.release());
1705
1706 webrtc::FakeConstraints constraints_no_receive;
1707 constraints_no_receive.SetMandatoryReceiveAudio(false);
1708 constraints_no_receive.SetMandatoryReceiveVideo(false);
1709
1710 // Test with a stream with tracks.
1711 mediastream_signaling_.SendAudioVideoStream1();
1712 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001713 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001714
1715 // TODO(perkj): Should the direction be set to SEND_ONLY?
1716 const cricket::ContentInfo* content =
1717 cricket::GetFirstAudioContent(answer->description());
1718 ASSERT_TRUE(content != NULL);
1719 EXPECT_FALSE(content->rejected);
1720
1721 // TODO(perkj): Should the direction be set to SEND_ONLY?
1722 content = cricket::GetFirstVideoContent(answer->description());
1723 ASSERT_TRUE(content != NULL);
1724 EXPECT_FALSE(content->rejected);
1725}
1726
1727TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1728 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001729 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001730 webrtc::FakeConstraints constraints;
1731 constraints.SetOptionalVAD(false);
1732 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001733 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734 const cricket::ContentInfo* content =
1735 cricket::GetFirstAudioContent(offer->description());
1736 EXPECT_TRUE(content != NULL);
1737 EXPECT_TRUE(VerifyNoCNCodecs(content));
1738}
1739
1740TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1741 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001742 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743 // Create a remote offer with audio and video content.
1744 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1745 SetRemoteDescriptionWithoutError(offer.release());
1746
1747 webrtc::FakeConstraints constraints;
1748 constraints.SetOptionalVAD(false);
1749 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001750 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 const cricket::ContentInfo* content =
1752 cricket::GetFirstAudioContent(answer->description());
1753 ASSERT_TRUE(content != NULL);
1754 EXPECT_TRUE(VerifyNoCNCodecs(content));
1755}
1756
1757// This test verifies the call setup when remote answer with audio only and
1758// later updates with video.
1759TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001760 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1762 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1763
1764 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001765 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
1767 cricket::MediaSessionOptions options;
1768 options.has_video = false;
1769 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1770
1771 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1772 // and answer;
1773 SetLocalDescriptionWithoutError(offer);
1774 SetRemoteDescriptionWithoutError(answer);
1775
1776 video_channel_ = media_engine_->GetVideoChannel(0);
1777 voice_channel_ = media_engine_->GetVoiceChannel(0);
1778
1779 ASSERT_TRUE(video_channel_ == NULL);
1780
1781 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1782 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1783 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1784
1785 // Let the remote end update the session descriptions, with Audio and Video.
1786 mediastream_signaling_.SendAudioVideoStream2();
1787 CreateAndSetRemoteOfferAndLocalAnswer();
1788
1789 video_channel_ = media_engine_->GetVideoChannel(0);
1790 voice_channel_ = media_engine_->GetVoiceChannel(0);
1791
1792 ASSERT_TRUE(video_channel_ != NULL);
1793 ASSERT_TRUE(voice_channel_ != NULL);
1794
1795 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1796 ASSERT_EQ(1u, video_channel_->send_streams().size());
1797 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1798 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1799 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1800 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1801 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1802 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1803
1804 // Change session back to audio only.
1805 mediastream_signaling_.UseOptionsAudioOnly();
1806 CreateAndSetRemoteOfferAndLocalAnswer();
1807
1808 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1809 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1810 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1811 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1812 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1813}
1814
1815// This test verifies the call setup when remote answer with video only and
1816// later updates with audio.
1817TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001818 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001819 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1820 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1821 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001822 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001823
1824 cricket::MediaSessionOptions options;
1825 options.has_audio = false;
1826 options.has_video = true;
1827 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1828 offer, options, cricket::SEC_ENABLED);
1829
1830 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1831 // and answer.
1832 SetLocalDescriptionWithoutError(offer);
1833 SetRemoteDescriptionWithoutError(answer);
1834
1835 video_channel_ = media_engine_->GetVideoChannel(0);
1836 voice_channel_ = media_engine_->GetVoiceChannel(0);
1837
1838 ASSERT_TRUE(voice_channel_ == NULL);
1839 ASSERT_TRUE(video_channel_ != NULL);
1840
1841 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1842 ASSERT_EQ(1u, video_channel_->send_streams().size());
1843 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1844
1845 // Update the session descriptions, with Audio and Video.
1846 mediastream_signaling_.SendAudioVideoStream2();
1847 CreateAndSetRemoteOfferAndLocalAnswer();
1848
1849 voice_channel_ = media_engine_->GetVoiceChannel(0);
1850 ASSERT_TRUE(voice_channel_ != NULL);
1851
1852 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1853 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1854 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1855 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1856
1857 // Change session back to video only.
1858 mediastream_signaling_.UseOptionsVideoOnly();
1859 CreateAndSetRemoteOfferAndLocalAnswer();
1860
1861 video_channel_ = media_engine_->GetVideoChannel(0);
1862 voice_channel_ = media_engine_->GetVoiceChannel(0);
1863
1864 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1865 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1866 ASSERT_EQ(1u, video_channel_->send_streams().size());
1867 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1868}
1869
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001871 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872 mediastream_signaling_.SendAudioVideoStream1();
1873 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001874 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001875 VerifyCryptoParams(offer->description());
1876 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001877 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878 VerifyCryptoParams(answer->description());
1879}
1880
1881TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001882 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883 session_->set_secure_policy(cricket::SEC_DISABLED);
1884 mediastream_signaling_.SendAudioVideoStream1();
1885 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001886 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001887 VerifyNoCryptoParams(offer->description(), false);
1888}
1889
1890TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001891 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001892 VerifyAnswerFromNonCryptoOffer();
1893}
1894
1895TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001896 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001897 VerifyAnswerFromCryptoOffer();
1898}
1899
1900TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
1901 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
1902 // local description is removed by the application, BUNDLE flag should be
1903 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001904 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001905 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1906 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1907 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001908 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 cricket::SessionDescription* offer_copy =
1910 offer->description()->Copy();
1911 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1912 JsepSessionDescription* modified_offer =
1913 new JsepSessionDescription(JsepSessionDescription::kOffer);
1914 modified_offer->Initialize(offer_copy, "1", "1");
1915
1916 SetLocalDescriptionWithoutError(modified_offer);
1917 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1918}
1919
1920TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001921 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001922 mediastream_signaling_.SendAudioVideoStream1();
1923 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1924 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1925 FakeConstraints constraints;
1926 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001927 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 SetLocalDescriptionWithoutError(offer);
1929 mediastream_signaling_.SendAudioVideoStream2();
1930 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1931 CreateRemoteAnswer(session_->local_description()));
1932 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1933 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1934 JsepSessionDescription* modified_answer =
1935 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1936 modified_answer->Initialize(answer_copy, "1", "1");
1937 SetRemoteDescriptionWithoutError(modified_answer);
1938 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1939 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1940
1941 video_channel_ = media_engine_->GetVideoChannel(0);
1942 voice_channel_ = media_engine_->GetVoiceChannel(0);
1943
1944 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1945 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1946
1947 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1948 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1949
1950 ASSERT_EQ(1u, video_channel_->send_streams().size());
1951 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1952 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1953 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1954}
1955
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001956// This test verifies that SetLocalDescription and SetRemoteDescription fails
1957// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1958TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001959 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001960 mediastream_signaling_.SendAudioVideoStream1();
1961 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1962 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1963 FakeConstraints constraints;
1964 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001965 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001966 std::string offer_str;
1967 offer->ToString(&offer_str);
1968 // Disable rtcp-mux
1969 const std::string rtcp_mux = "rtcp-mux";
1970 const std::string xrtcp_mux = "xrtcp-mux";
1971 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1972 xrtcp_mux.c_str(), xrtcp_mux.length(),
1973 &offer_str);
1974 JsepSessionDescription *local_offer =
1975 new JsepSessionDescription(JsepSessionDescription::kOffer);
1976 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
1977 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
1978 JsepSessionDescription *remote_offer =
1979 new JsepSessionDescription(JsepSessionDescription::kOffer);
1980 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
1981 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
1982 // Trying unmodified SDP.
1983 SetLocalDescriptionWithoutError(offer);
1984}
1985
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001987 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001988 mediastream_signaling_.SendAudioVideoStream1();
1989 CreateAndSetRemoteOfferAndLocalAnswer();
1990 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
1991 ASSERT_TRUE(channel != NULL);
1992 ASSERT_EQ(1u, channel->recv_streams().size());
1993 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
1994 double left_vol, right_vol;
1995 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1996 EXPECT_EQ(1, left_vol);
1997 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001998 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
1999 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2001 EXPECT_EQ(0, left_vol);
2002 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002003 EXPECT_EQ(0, renderer->channel_id());
2004 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2006 EXPECT_EQ(1, left_vol);
2007 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002008 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002009}
2010
2011TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002012 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002013 mediastream_signaling_.SendAudioVideoStream1();
2014 CreateAndSetRemoteOfferAndLocalAnswer();
2015 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2016 ASSERT_TRUE(channel != NULL);
2017 ASSERT_EQ(1u, channel->send_streams().size());
2018 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2019 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2020
2021 cricket::AudioOptions options;
2022 options.echo_cancellation.Set(true);
2023
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002024 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2025 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2027 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002028 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002030 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002031 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2032 bool value;
2033 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2034 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002035 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002036}
2037
2038TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002039 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 mediastream_signaling_.SendAudioVideoStream1();
2041 CreateAndSetRemoteOfferAndLocalAnswer();
2042 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2043 ASSERT_TRUE(channel != NULL);
2044 ASSERT_LT(0u, channel->renderers().size());
2045 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2046 ASSERT_EQ(1u, channel->recv_streams().size());
2047 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2048 cricket::FakeVideoRenderer renderer;
2049 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2050 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2051 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2052 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2053}
2054
2055TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002056 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002057 mediastream_signaling_.SendAudioVideoStream1();
2058 CreateAndSetRemoteOfferAndLocalAnswer();
2059 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2060 ASSERT_TRUE(channel != NULL);
2061 ASSERT_EQ(1u, channel->send_streams().size());
2062 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2063 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2064 cricket::VideoOptions* options = NULL;
2065 session_->SetVideoSend(send_ssrc, false, options);
2066 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2067 session_->SetVideoSend(send_ssrc, true, options);
2068 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2069}
2070
2071TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2072 TestCanInsertDtmf(false);
2073}
2074
2075TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2076 TestCanInsertDtmf(true);
2077}
2078
2079TEST_F(WebRtcSessionTest, InsertDtmf) {
2080 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002081 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002082 mediastream_signaling_.SendAudioVideoStream1();
2083 CreateAndSetRemoteOfferAndLocalAnswer();
2084 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2085 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2086
2087 // Insert DTMF
2088 const int expected_flags = DF_SEND;
2089 const int expected_duration = 90;
2090 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2091 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2092 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2093
2094 // Verify
2095 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2096 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2097 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2098 expected_duration, expected_flags));
2099 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2100 expected_duration, expected_flags));
2101 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2102 expected_duration, expected_flags));
2103}
2104
2105// This test verifies the |initiator| flag when session initiates the call.
2106TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002107 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002109 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002110 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2111 SetLocalDescriptionWithoutError(offer);
2112 EXPECT_TRUE(session_->initiator());
2113 SetRemoteDescriptionWithoutError(answer);
2114 EXPECT_TRUE(session_->initiator());
2115}
2116
2117// This test verifies the |initiator| flag when session receives the call.
2118TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002119 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002120 EXPECT_FALSE(session_->initiator());
2121 SessionDescriptionInterface* offer = CreateRemoteOffer();
2122 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002123 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002124
2125 EXPECT_FALSE(session_->initiator());
2126 SetLocalDescriptionWithoutError(answer);
2127 EXPECT_FALSE(session_->initiator());
2128}
2129
2130// This test verifies the ice protocol type at initiator of the call
2131// if |a=ice-options:google-ice| is present in answer.
2132TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002133 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002134 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002135 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002136 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002137 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002138 SetLocalDescriptionWithoutError(offer);
2139 std::string sdp;
2140 EXPECT_TRUE(answer->ToString(&sdp));
2141 // Adding ice-options to the session level.
2142 InjectAfter("t=0 0\r\n",
2143 "a=ice-options:google-ice\r\n",
2144 &sdp);
2145 SessionDescriptionInterface* answer_with_gice =
2146 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2147 SetRemoteDescriptionWithoutError(answer_with_gice);
2148 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2149 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2150}
2151
2152// This test verifies the ice protocol type at initiator of the call
2153// if ICE RFC5245 is supported in answer.
2154TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002155 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002156 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002157 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002158 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2159 SetLocalDescriptionWithoutError(offer);
2160
2161 SetRemoteDescriptionWithoutError(answer);
2162 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2163 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2164}
2165
2166// This test verifies the ice protocol type at receiver side of the call if
2167// receiver decides to use google-ice.
2168TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002169 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002170 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002171 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002172 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002173 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002174 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002175 std::string sdp;
2176 EXPECT_TRUE(answer->ToString(&sdp));
2177 // Adding ice-options to the session level.
2178 InjectAfter("t=0 0\r\n",
2179 "a=ice-options:google-ice\r\n",
2180 &sdp);
2181 SessionDescriptionInterface* answer_with_gice =
2182 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2183 SetLocalDescriptionWithoutError(answer_with_gice);
2184 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2185 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2186}
2187
2188// This test verifies the ice protocol type at receiver side of the call if
2189// receiver decides to use ice RFC 5245.
2190TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002191 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002192 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002193 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002195 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002196 SetLocalDescriptionWithoutError(answer);
2197 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2198 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2199}
2200
2201// This test verifies the session state when ICE RFC5245 in offer and
2202// ICE google-ice in answer.
2203TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002204 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002205 mediastream_signaling_.SendAudioVideoStream1();
2206 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002207 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002208 std::string offer_str;
2209 offer->ToString(&offer_str);
2210 // Disable google-ice
2211 const std::string gice_option = "google-ice";
2212 const std::string xgoogle_xice = "xgoogle-xice";
2213 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2214 xgoogle_xice.c_str(), xgoogle_xice.length(),
2215 &offer_str);
2216 JsepSessionDescription *ice_only_offer =
2217 new JsepSessionDescription(JsepSessionDescription::kOffer);
2218 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2219 SetLocalDescriptionWithoutError(ice_only_offer);
2220 std::string original_offer_sdp;
2221 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002222 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002223 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002224 original_offer_sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002225 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002226 pranswer_with_gice);
2227 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002228 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002229 original_offer_sdp, NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002230 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002231 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002232}
2233
2234// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2235TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002236 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002238 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 SetLocalDescriptionWithoutError(offer);
2240 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2241 CreateRemoteAnswer(session_->local_description()));
2242
2243 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2244 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002245 JsepSessionDescription* modified_answer =
2246 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002247
2248 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2249 answer->session_id(),
2250 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002251 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002252
2253 // Modifying content names.
2254 std::string sdp;
2255 EXPECT_TRUE(answer->ToString(&sdp));
2256 const std::string kAudioMid = "a=mid:audio";
2257 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2258
2259 // Replacing |audio| with |audio_content_name|.
2260 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2261 kAudioMidReplaceStr.c_str(),
2262 kAudioMidReplaceStr.length(),
2263 &sdp);
2264
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002265 SessionDescriptionInterface* modified_answer1 =
2266 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2267 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268
2269 SetRemoteDescriptionWithoutError(answer.release());
2270}
2271
2272// Verifying remote offer and local answer have matching m-lines as per
2273// RFC 3264.
2274TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002275 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 mediastream_signaling_.SendAudioVideoStream1();
2277 SessionDescriptionInterface* offer = CreateRemoteOffer();
2278 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002279 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280
2281 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2282 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002283 JsepSessionDescription* modified_answer =
2284 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002285
2286 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2287 answer->session_id(),
2288 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002289 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002290 SetLocalDescriptionWithoutError(answer);
2291}
2292
2293// This test verifies that WebRtcSession does not start candidate allocation
2294// before SetLocalDescription is called.
2295TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002296 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002297 mediastream_signaling_.SendAudioVideoStream1();
2298 SessionDescriptionInterface* offer = CreateRemoteOffer();
2299 cricket::Candidate candidate;
2300 candidate.set_component(1);
2301 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2302 candidate);
2303 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2304 cricket::Candidate candidate1;
2305 candidate1.set_component(1);
2306 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2307 candidate1);
2308 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2309 SetRemoteDescriptionWithoutError(offer);
2310 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2311 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2312
2313 // Pump for 1 second and verify that no candidates are generated.
2314 talk_base::Thread::Current()->ProcessMessages(1000);
2315 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2316 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2317
wu@webrtc.org91053e72013-08-10 07:18:04 +00002318 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002319 SetLocalDescriptionWithoutError(answer);
2320 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2321 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2322 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2323}
2324
2325// This test verifies that crypto parameter is updated in local session
2326// description as per security policy set in MediaSessionDescriptionFactory.
2327TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002328 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002329 mediastream_signaling_.SendAudioVideoStream1();
2330 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002331 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332
2333 // Making sure SetLocalDescription correctly sets crypto value in
2334 // SessionDescription object after de-serialization of sdp string. The value
2335 // will be set as per MediaSessionDescriptionFactory.
2336 std::string offer_str;
2337 offer->ToString(&offer_str);
2338 SessionDescriptionInterface* jsep_offer_str =
2339 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2340 SetLocalDescriptionWithoutError(jsep_offer_str);
2341 EXPECT_TRUE(session_->voice_channel()->secure_required());
2342 EXPECT_TRUE(session_->video_channel()->secure_required());
2343}
2344
2345// This test verifies the crypto parameter when security is disabled.
2346TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002347 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002348 mediastream_signaling_.SendAudioVideoStream1();
2349 session_->set_secure_policy(cricket::SEC_DISABLED);
2350 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002351 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352
2353 // Making sure SetLocalDescription correctly sets crypto value in
2354 // SessionDescription object after de-serialization of sdp string. The value
2355 // will be set as per MediaSessionDescriptionFactory.
2356 std::string offer_str;
2357 offer->ToString(&offer_str);
2358 SessionDescriptionInterface *jsep_offer_str =
2359 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2360 SetLocalDescriptionWithoutError(jsep_offer_str);
2361 EXPECT_FALSE(session_->voice_channel()->secure_required());
2362 EXPECT_FALSE(session_->video_channel()->secure_required());
2363}
2364
2365// This test verifies that an answer contains new ufrag and password if an offer
2366// with new ufrag and password is received.
2367TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002368 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002369 cricket::MediaSessionOptions options;
2370 options.has_audio = true;
2371 options.has_video = true;
2372 talk_base::scoped_ptr<JsepSessionDescription> offer(
2373 CreateRemoteOffer(options));
2374 SetRemoteDescriptionWithoutError(offer.release());
2375
2376 mediastream_signaling_.SendAudioVideoStream1();
2377 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002378 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002379 SetLocalDescriptionWithoutError(answer.release());
2380
2381 // Receive an offer with new ufrag and password.
2382 options.transport_options.ice_restart = true;
2383 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002384 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002385 SetRemoteDescriptionWithoutError(updated_offer1.release());
2386
2387 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002388 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002389
2390 CompareIceUfragAndPassword(updated_answer1->description(),
2391 session_->local_description()->description(),
2392 false);
2393
2394 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002395}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002396
wu@webrtc.org91053e72013-08-10 07:18:04 +00002397// This test verifies that an answer contains old ufrag and password if an offer
2398// with old ufrag and password is received.
2399TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2400 Init(NULL);
2401 cricket::MediaSessionOptions options;
2402 options.has_audio = true;
2403 options.has_video = true;
2404 talk_base::scoped_ptr<JsepSessionDescription> offer(
2405 CreateRemoteOffer(options));
2406 SetRemoteDescriptionWithoutError(offer.release());
2407
2408 mediastream_signaling_.SendAudioVideoStream1();
2409 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2410 CreateAnswer(NULL));
2411 SetLocalDescriptionWithoutError(answer.release());
2412
2413 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002414 options.transport_options.ice_restart = false;
2415 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002416 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002417 SetRemoteDescriptionWithoutError(updated_offer2.release());
2418
2419 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002420 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002421
2422 CompareIceUfragAndPassword(updated_answer2->description(),
2423 session_->local_description()->description(),
2424 true);
2425
2426 SetLocalDescriptionWithoutError(updated_answer2.release());
2427}
2428
2429TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002430 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002431 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002432 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002433 const std::string session_id_orig = offer->session_id();
2434 const std::string session_version_orig = offer->session_version();
2435 SetLocalDescriptionWithoutError(offer);
2436
2437 video_channel_ = media_engine_->GetVideoChannel(0);
2438 video_channel_->set_fail_set_send_codecs(true);
2439
2440 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002441 SessionDescriptionInterface* answer =
2442 CreateRemoteAnswer(session_->local_description());
2443 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002444}
2445
2446// Runs the loopback call test with BUNDLE and STUN disabled.
2447TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2448 // Lets try with only UDP ports.
2449 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2450 cricket::PORTALLOCATOR_DISABLE_TCP |
2451 cricket::PORTALLOCATOR_DISABLE_STUN |
2452 cricket::PORTALLOCATOR_DISABLE_RELAY);
2453 TestLoopbackCall();
2454}
2455
2456// Regression-test for a crash which should have been an error.
2457TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002458 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002459 cricket::MediaSessionOptions options;
2460 options.has_audio = true;
2461 options.has_video = true;
2462
2463 session_->SetError(cricket::BaseSession::ERROR_CONTENT);
2464 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2465 SessionDescriptionInterface* answer =
2466 CreateRemoteAnswer(offer, options);
2467 SetRemoteDescriptionExpectError(kSessionError, offer);
2468 SetLocalDescriptionExpectError(kSessionError, answer);
2469 // Not crashing is our success.
2470}
2471
2472TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2473 constraints_.reset(new FakeConstraints());
2474 constraints_->AddOptional(
2475 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002476 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002477
2478 SetLocalDescriptionWithDataChannel();
2479 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2480}
2481
2482TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2483 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2484
2485 constraints_.reset(new FakeConstraints());
2486 constraints_->AddOptional(
2487 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2488 constraints_->AddOptional(
2489 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2490 constraints_->AddOptional(
2491 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002492 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002493
2494 SetLocalDescriptionWithDataChannel();
2495 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2496}
2497
2498TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2499 constraints_.reset(new FakeConstraints());
2500 constraints_->AddOptional(
2501 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002502 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002503
2504 SetLocalDescriptionWithDataChannel();
2505 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2506}
2507
2508TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2509 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2510
2511 constraints_.reset(new FakeConstraints());
2512 constraints_->AddOptional(
2513 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2514 constraints_->AddOptional(
2515 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002516 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002517
2518 SetLocalDescriptionWithDataChannel();
2519 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2520}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002521
2522// Verifies that CreateOffer succeeds when CreateOffer is called before async
2523// identity generation is finished.
2524TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
2525 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2526 InitWithAsyncDtls(false);
2527
2528 EXPECT_TRUE(session_->waiting_for_identity());
2529 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2530 EXPECT_TRUE(offer != NULL);
2531}
2532
2533// Verifies that CreateAnswer succeeds when CreateOffer is called before async
2534// identity generation is finished.
2535TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
2536 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2537 InitWithAsyncDtls(false);
2538
2539 cricket::MediaSessionOptions options;
2540 scoped_ptr<JsepSessionDescription> offer(
2541 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
2542 ASSERT_TRUE(offer.get() != NULL);
2543 SetRemoteDescriptionWithoutError(offer.release());
2544
2545 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2546 EXPECT_TRUE(answer != NULL);
2547}
2548
2549// Verifies that CreateOffer succeeds when CreateOffer is called after async
2550// identity generation is finished.
2551TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
2552 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2553 InitWithAsyncDtls(false);
2554
2555 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2556 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2557 EXPECT_TRUE(offer != NULL);
2558}
2559
2560// Verifies that CreateOffer fails when CreateOffer is called after async
2561// identity generation fails.
2562TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
2563 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2564 InitWithAsyncDtls(true);
2565
2566 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2567 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2568 EXPECT_TRUE(offer == NULL);
2569}
2570
2571// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
2572// before async identity generation is finished.
2573TEST_F(WebRtcSessionTest,
2574 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
2575 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2576 VerifyMultipleAsyncCreateDescription(
2577 true, CreateSessionDescriptionRequest::kOffer);
2578}
2579
2580// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
2581// before async identity generation fails.
2582TEST_F(WebRtcSessionTest,
2583 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
2584 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2585 VerifyMultipleAsyncCreateDescription(
2586 false, CreateSessionDescriptionRequest::kOffer);
2587}
2588
2589// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
2590// before async identity generation is finished.
2591TEST_F(WebRtcSessionTest,
2592 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
2593 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2594 VerifyMultipleAsyncCreateDescription(
2595 true, CreateSessionDescriptionRequest::kAnswer);
2596}
2597
2598// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
2599// before async identity generation fails.
2600TEST_F(WebRtcSessionTest,
2601 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
2602 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2603 VerifyMultipleAsyncCreateDescription(
2604 false, CreateSessionDescriptionRequest::kAnswer);
2605}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002606// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
2607// currently fails because upon disconnection and reconnection OnIceComplete is
2608// called more than once without returning to IceGatheringGathering.