blob: 71691df2f313739656d3062e10d75cfc22388c86 [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"
35#include "talk/app/webrtc/webrtcsession.h"
36#include "talk/base/fakenetwork.h"
37#include "talk/base/firewallsocketserver.h"
38#include "talk/base/gunit.h"
39#include "talk/base/logging.h"
40#include "talk/base/network.h"
41#include "talk/base/physicalsocketserver.h"
42#include "talk/base/sslstreamadapter.h"
43#include "talk/base/stringutils.h"
44#include "talk/base/thread.h"
45#include "talk/base/virtualsocketserver.h"
46#include "talk/media/base/fakemediaengine.h"
47#include "talk/media/base/fakevideorenderer.h"
48#include "talk/media/base/mediachannel.h"
49#include "talk/media/devices/fakedevicemanager.h"
50#include "talk/p2p/base/stunserver.h"
51#include "talk/p2p/base/teststunserver.h"
52#include "talk/p2p/client/basicportallocator.h"
53#include "talk/session/media/channelmanager.h"
54#include "talk/session/media/mediasession.h"
55
56#define MAYBE_SKIP_TEST(feature) \
57 if (!(feature())) { \
58 LOG(LS_INFO) << "Feature disabled... skipping"; \
59 return; \
60 }
61
62using cricket::BaseSession;
63using cricket::DF_PLAY;
64using cricket::DF_SEND;
65using cricket::FakeVoiceMediaChannel;
66using cricket::NS_GINGLE_P2P;
67using cricket::NS_JINGLE_ICE_UDP;
68using cricket::TransportInfo;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069using talk_base::SocketAddress;
70using talk_base::scoped_ptr;
71using webrtc::CreateSessionDescription;
72using webrtc::FakeConstraints;
73using webrtc::IceCandidateCollection;
74using webrtc::JsepIceCandidate;
75using webrtc::JsepSessionDescription;
76using webrtc::PeerConnectionInterface;
77using webrtc::SessionDescriptionInterface;
78using webrtc::StreamCollection;
79using webrtc::kMlineMismatch;
80using webrtc::kSdpWithoutCrypto;
81using webrtc::kSessionError;
82using webrtc::kSetLocalSdpFailed;
83using webrtc::kSetRemoteSdpFailed;
84using webrtc::kPushDownAnswerTDFailed;
85using webrtc::kPushDownPranswerTDFailed;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000086using webrtc::kBundleWithoutRtcpMux;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
88static const SocketAddress kClientAddr1("11.11.11.11", 0);
89static const SocketAddress kClientAddr2("22.22.22.22", 0);
90static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
91
92static const char kSessionVersion[] = "1";
93
94static const char kStream1[] = "stream1";
95static const char kVideoTrack1[] = "video1";
96static const char kAudioTrack1[] = "audio1";
97
98static const char kStream2[] = "stream2";
99static const char kVideoTrack2[] = "video2";
100static const char kAudioTrack2[] = "audio2";
101
102// 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
205class FakeMediaStreamSignaling : public webrtc::MediaStreamSignaling,
206 public webrtc::MediaStreamSignalingObserver {
207 public:
208 FakeMediaStreamSignaling() :
209 webrtc::MediaStreamSignaling(talk_base::Thread::Current(), this) {
210 }
211
212 void SendAudioVideoStream1() {
213 ClearLocalStreams();
214 AddLocalStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
215 }
216
217 void SendAudioVideoStream2() {
218 ClearLocalStreams();
219 AddLocalStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
220 }
221
222 void SendAudioVideoStream1And2() {
223 ClearLocalStreams();
224 AddLocalStream(CreateStream(kStream1, kAudioTrack1, kVideoTrack1));
225 AddLocalStream(CreateStream(kStream2, kAudioTrack2, kVideoTrack2));
226 }
227
228 void SendNothing() {
229 ClearLocalStreams();
230 }
231
232 void UseOptionsAudioOnly() {
233 ClearLocalStreams();
234 AddLocalStream(CreateStream(kStream2, kAudioTrack2, ""));
235 }
236
237 void UseOptionsVideoOnly() {
238 ClearLocalStreams();
239 AddLocalStream(CreateStream(kStream2, "", kVideoTrack2));
240 }
241
242 void ClearLocalStreams() {
243 while (local_streams()->count() != 0) {
244 RemoveLocalStream(local_streams()->at(0));
245 }
246 }
247
248 // Implements MediaStreamSignalingObserver.
249 virtual void OnAddRemoteStream(webrtc::MediaStreamInterface* stream) {
250 }
251 virtual void OnRemoveRemoteStream(webrtc::MediaStreamInterface* stream) {
252 }
253 virtual void OnAddDataChannel(webrtc::DataChannelInterface* data_channel) {
254 }
255 virtual void OnAddLocalAudioTrack(webrtc::MediaStreamInterface* stream,
256 webrtc::AudioTrackInterface* audio_track,
257 uint32 ssrc) {
258 }
259 virtual void OnAddLocalVideoTrack(webrtc::MediaStreamInterface* stream,
260 webrtc::VideoTrackInterface* video_track,
261 uint32 ssrc) {
262 }
263 virtual void OnAddRemoteAudioTrack(webrtc::MediaStreamInterface* stream,
264 webrtc::AudioTrackInterface* audio_track,
265 uint32 ssrc) {
266 }
267
268 virtual void OnAddRemoteVideoTrack(webrtc::MediaStreamInterface* stream,
269 webrtc::VideoTrackInterface* video_track,
270 uint32 ssrc) {
271 }
272
273 virtual void OnRemoveRemoteAudioTrack(
274 webrtc::MediaStreamInterface* stream,
275 webrtc::AudioTrackInterface* audio_track) {
276 }
277
278 virtual void OnRemoveRemoteVideoTrack(
279 webrtc::MediaStreamInterface* stream,
280 webrtc::VideoTrackInterface* video_track) {
281 }
282
283 virtual void OnRemoveLocalAudioTrack(
284 webrtc::MediaStreamInterface* stream,
285 webrtc::AudioTrackInterface* audio_track) {
286 }
287 virtual void OnRemoveLocalVideoTrack(
288 webrtc::MediaStreamInterface* stream,
289 webrtc::VideoTrackInterface* video_track) {
290 }
291 virtual void OnRemoveLocalStream(webrtc::MediaStreamInterface* stream) {
292 }
293
294 private:
295 talk_base::scoped_refptr<webrtc::MediaStreamInterface> CreateStream(
296 const std::string& stream_label,
297 const std::string& audio_track_id,
298 const std::string& video_track_id) {
299 talk_base::scoped_refptr<webrtc::MediaStreamInterface> stream(
300 webrtc::MediaStream::Create(stream_label));
301
302 if (!audio_track_id.empty()) {
303 talk_base::scoped_refptr<webrtc::AudioTrackInterface> audio_track(
304 webrtc::AudioTrack::Create(audio_track_id, NULL));
305 stream->AddTrack(audio_track);
306 }
307
308 if (!video_track_id.empty()) {
309 talk_base::scoped_refptr<webrtc::VideoTrackInterface> video_track(
310 webrtc::VideoTrack::Create(video_track_id, NULL));
311 stream->AddTrack(video_track);
312 }
313 return stream;
314 }
315
316 cricket::MediaSessionOptions options_;
317};
318
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000319class FakeAudioRenderer : public cricket::AudioRenderer {
320 public:
321 FakeAudioRenderer() : channel_id_(-1) {}
322
323 virtual void AddChannel(int channel_id) OVERRIDE {
324 ASSERT(channel_id_ == -1);
325 channel_id_ = channel_id;
326 }
327 virtual void RemoveChannel(int channel_id) OVERRIDE {
328 ASSERT(channel_id == channel_id_);
329 channel_id_ = -1;
330 }
331
332 int channel_id() const { return channel_id_; }
333 private:
334 int channel_id_;
335};
336
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000337class WebRtcSessionTest : public testing::Test {
338 protected:
339 // TODO Investigate why ChannelManager crashes, if it's created
340 // after stun_server.
341 WebRtcSessionTest()
342 : media_engine_(new cricket::FakeMediaEngine()),
343 data_engine_(new cricket::FakeDataEngine()),
344 device_manager_(new cricket::FakeDeviceManager()),
345 channel_manager_(new cricket::ChannelManager(
346 media_engine_, data_engine_, device_manager_,
347 new cricket::CaptureManager(), talk_base::Thread::Current())),
348 tdesc_factory_(new cricket::TransportDescriptionFactory()),
349 desc_factory_(new cricket::MediaSessionDescriptionFactory(
350 channel_manager_.get(), tdesc_factory_.get())),
351 pss_(new talk_base::PhysicalSocketServer),
352 vss_(new talk_base::VirtualSocketServer(pss_.get())),
353 fss_(new talk_base::FirewallSocketServer(vss_.get())),
354 ss_scope_(fss_.get()),
355 stun_server_(talk_base::Thread::Current(), kStunAddr),
356 allocator_(&network_manager_, kStunAddr,
357 SocketAddress(), SocketAddress(), SocketAddress()) {
358 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
359 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
360 cricket::PORTALLOCATOR_DISABLE_RELAY |
361 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
362 EXPECT_TRUE(channel_manager_->Init());
363 desc_factory_->set_add_legacy_streams(false);
364 }
365
366 void AddInterface(const SocketAddress& addr) {
367 network_manager_.AddInterface(addr);
368 }
369
370 void Init() {
371 ASSERT_TRUE(session_.get() == NULL);
372 session_.reset(new WebRtcSessionForTest(
373 channel_manager_.get(), talk_base::Thread::Current(),
374 talk_base::Thread::Current(), &allocator_,
375 &observer_,
376 &mediastream_signaling_));
377
378 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
379 observer_.ice_connection_state_);
380 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
381 observer_.ice_gathering_state_);
382
383 EXPECT_TRUE(session_->Initialize(constraints_.get()));
384 }
385
386 void InitWithDtmfCodec() {
387 // Add kTelephoneEventCodec for dtmf test.
388 std::vector<cricket::AudioCodec> codecs;
389 codecs.push_back(kTelephoneEventCodec);
390 media_engine_->SetAudioCodecs(codecs);
391 desc_factory_->set_audio_codecs(codecs);
392 Init();
393 }
394
395 void InitWithDtls() {
396 constraints_.reset(new FakeConstraints());
397 constraints_->AddOptional(
398 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
399
400 Init();
401 }
402
403 // Creates a local offer and applies it. Starts ice.
404 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
405 // to decide which streams to create.
406 void InitiateCall() {
407 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
408 SetLocalDescriptionWithoutError(offer);
409 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
410 observer_.ice_gathering_state_,
411 kIceCandidatesTimeout);
412 }
413
414 bool ChannelsExist() {
415 return (session_->voice_channel() != NULL &&
416 session_->video_channel() != NULL);
417 }
418
419 void CheckTransportChannels() {
420 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
421 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
422 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
423 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
424 }
425
426 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
427 ASSERT_TRUE(session_.get() != NULL);
428 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
429 ASSERT_TRUE(content != NULL);
430 const cricket::AudioContentDescription* audio_content =
431 static_cast<const cricket::AudioContentDescription*>(
432 content->description);
433 ASSERT_TRUE(audio_content != NULL);
434 ASSERT_EQ(1U, audio_content->cryptos().size());
435 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
436 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
437 audio_content->cryptos()[0].cipher_suite);
438 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
439 audio_content->protocol());
440
441 content = cricket::GetFirstVideoContent(sdp);
442 ASSERT_TRUE(content != NULL);
443 const cricket::VideoContentDescription* video_content =
444 static_cast<const cricket::VideoContentDescription*>(
445 content->description);
446 ASSERT_TRUE(video_content != NULL);
447 ASSERT_EQ(1U, video_content->cryptos().size());
448 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
449 video_content->cryptos()[0].cipher_suite);
450 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
451 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
452 video_content->protocol());
453 }
454
455 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
456 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
457 ASSERT_TRUE(content != NULL);
458 const cricket::AudioContentDescription* audio_content =
459 static_cast<const cricket::AudioContentDescription*>(
460 content->description);
461 ASSERT_TRUE(audio_content != NULL);
462 ASSERT_EQ(0U, audio_content->cryptos().size());
463
464 content = cricket::GetFirstVideoContent(sdp);
465 ASSERT_TRUE(content != NULL);
466 const cricket::VideoContentDescription* video_content =
467 static_cast<const cricket::VideoContentDescription*>(
468 content->description);
469 ASSERT_TRUE(video_content != NULL);
470 ASSERT_EQ(0U, video_content->cryptos().size());
471
472 if (dtls) {
473 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
474 audio_content->protocol());
475 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
476 video_content->protocol());
477 } else {
478 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
479 audio_content->protocol());
480 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
481 video_content->protocol());
482 }
483 }
484
485 // Set the internal fake description factories to do DTLS-SRTP.
486 void SetFactoryDtlsSrtp() {
487 desc_factory_->set_secure(cricket::SEC_ENABLED);
488 std::string identity_name = "WebRTC" +
489 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000490 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
491 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
493 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
494 }
495
496 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
497 bool expected) {
498 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
499 ASSERT_TRUE(audio != NULL);
500 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
501 if (expected) {
502 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
503 identity_fingerprint->algorithm);
504 }
505 const TransportInfo* video = sdp->GetTransportInfoByName("video");
506 ASSERT_TRUE(video != NULL);
507 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
508 if (expected) {
509 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
510 identity_fingerprint->algorithm);
511 }
512 }
513
514 void VerifyAnswerFromNonCryptoOffer() {
515 // Create a SDP without Crypto.
516 cricket::MediaSessionOptions options;
517 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000518 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000520 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000521 VerifyNoCryptoParams(offer->description(), false);
522 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000523 offer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 const webrtc::SessionDescriptionInterface* answer =
525 session_->CreateAnswer(NULL);
526 // Answer should be NULL as no crypto params in offer.
527 ASSERT_TRUE(answer == NULL);
528 }
529
530 void VerifyAnswerFromCryptoOffer() {
531 cricket::MediaSessionOptions options;
532 options.has_video = true;
533 options.bundle_enabled = true;
534 scoped_ptr<JsepSessionDescription> offer(
535 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
536 ASSERT_TRUE(offer.get() != NULL);
537 VerifyCryptoParams(offer->description());
538 SetRemoteDescriptionWithoutError(offer.release());
539 scoped_ptr<SessionDescriptionInterface> answer(
540 session_->CreateAnswer(NULL));
541 ASSERT_TRUE(answer.get() != NULL);
542 VerifyCryptoParams(answer->description());
543 }
544
545 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
546 const cricket::SessionDescription* desc2,
547 bool expect_equal) {
548 if (desc1->contents().size() != desc2->contents().size()) {
549 EXPECT_FALSE(expect_equal);
550 return;
551 }
552
553 const cricket::ContentInfos& contents = desc1->contents();
554 cricket::ContentInfos::const_iterator it = contents.begin();
555
556 for (; it != contents.end(); ++it) {
557 const cricket::TransportDescription* transport_desc1 =
558 desc1->GetTransportDescriptionByName(it->name);
559 const cricket::TransportDescription* transport_desc2 =
560 desc2->GetTransportDescriptionByName(it->name);
561 if (!transport_desc1 || !transport_desc2) {
562 EXPECT_FALSE(expect_equal);
563 return;
564 }
565 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
566 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
567 EXPECT_FALSE(expect_equal);
568 return;
569 }
570 }
571 EXPECT_TRUE(expect_equal);
572 }
573 // Creates a remote offer and and applies it as a remote description,
574 // creates a local answer and applies is as a local description.
575 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
576 // to decide which local and remote streams to create.
577 void CreateAndSetRemoteOfferAndLocalAnswer() {
578 SessionDescriptionInterface* offer = CreateRemoteOffer();
579 SetRemoteDescriptionWithoutError(offer);
580 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
581 SetLocalDescriptionWithoutError(answer);
582 }
583 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
584 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
585 }
586 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
587 BaseSession::State expected_state) {
588 SetLocalDescriptionWithoutError(desc);
589 EXPECT_EQ(expected_state, session_->state());
590 }
591 void SetLocalDescriptionExpectError(const std::string& expected_error,
592 SessionDescriptionInterface* desc) {
593 std::string error;
594 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
595 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
596 EXPECT_NE(std::string::npos, error.find(expected_error));
597 }
598 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
599 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
600 }
601 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
602 BaseSession::State expected_state) {
603 SetRemoteDescriptionWithoutError(desc);
604 EXPECT_EQ(expected_state, session_->state());
605 }
606 void SetRemoteDescriptionExpectError(const std::string& expected_error,
607 SessionDescriptionInterface* desc) {
608 std::string error;
609 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
610 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
611 EXPECT_NE(std::string::npos, error.find(expected_error));
612 }
613
614 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
615 SessionDescriptionInterface** nocrypto_answer) {
616 // Create a SDP without Crypto.
617 cricket::MediaSessionOptions options;
618 options.has_video = true;
619 options.bundle_enabled = true;
620 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
621 ASSERT_TRUE(*offer != NULL);
622 VerifyCryptoParams((*offer)->description());
623
624 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
625 cricket::SEC_DISABLED);
626 EXPECT_TRUE(*nocrypto_answer != NULL);
627 }
628
629 JsepSessionDescription* CreateRemoteOfferWithVersion(
630 cricket::MediaSessionOptions options,
631 cricket::SecurePolicy secure_policy,
632 const std::string& session_version,
633 const SessionDescriptionInterface* current_desc) {
634 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
635 const cricket::SessionDescription* cricket_desc = NULL;
636 if (current_desc) {
637 cricket_desc = current_desc->description();
638 session_id = current_desc->session_id();
639 }
640
641 desc_factory_->set_secure(secure_policy);
642 JsepSessionDescription* offer(
643 new JsepSessionDescription(JsepSessionDescription::kOffer));
644 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
645 session_id, session_version)) {
646 delete offer;
647 offer = NULL;
648 }
649 return offer;
650 }
651 JsepSessionDescription* CreateRemoteOffer(
652 cricket::MediaSessionOptions options) {
653 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
654 kSessionVersion, NULL);
655 }
656 JsepSessionDescription* CreateRemoteOffer(
657 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
658 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
659 }
660 JsepSessionDescription* CreateRemoteOffer(
661 cricket::MediaSessionOptions options,
662 const SessionDescriptionInterface* current_desc) {
663 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
664 kSessionVersion, current_desc);
665 }
666
667 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
668 // before this function to decide which streams to create.
669 JsepSessionDescription* CreateRemoteOffer() {
670 cricket::MediaSessionOptions options;
671 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
672 return CreateRemoteOffer(options, session_->remote_description());
673 }
674
675 JsepSessionDescription* CreateRemoteAnswer(
676 const SessionDescriptionInterface* offer,
677 cricket::MediaSessionOptions options,
678 cricket::SecurePolicy policy) {
679 desc_factory_->set_secure(policy);
680 const std::string session_id =
681 talk_base::ToString(talk_base::CreateRandomId64());
682 JsepSessionDescription* answer(
683 new JsepSessionDescription(JsepSessionDescription::kAnswer));
684 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
685 options, NULL),
686 session_id, kSessionVersion)) {
687 delete answer;
688 answer = NULL;
689 }
690 return answer;
691 }
692
693 JsepSessionDescription* CreateRemoteAnswer(
694 const SessionDescriptionInterface* offer,
695 cricket::MediaSessionOptions options) {
696 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
697 }
698
699 // Creates an answer session description with streams based on
700 // |mediastream_signaling_|. Call
701 // mediastream_signaling_.UseOptionsWithStreamX() before this function
702 // to decide which streams to create.
703 JsepSessionDescription* CreateRemoteAnswer(
704 const SessionDescriptionInterface* offer) {
705 cricket::MediaSessionOptions options;
706 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
707 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
708 }
709
710 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
711 AddInterface(kClientAddr1);
712 Init();
713 mediastream_signaling_.SendAudioVideoStream1();
714 FakeConstraints constraints;
715 constraints.SetMandatoryUseRtpMux(bundle);
716 SessionDescriptionInterface* offer = session_->CreateOffer(&constraints);
717 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
718 // and answer.
719 SetLocalDescriptionWithoutError(offer);
720
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000721 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
722 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723 std::string sdp;
724 EXPECT_TRUE(answer->ToString(&sdp));
725
726 size_t expected_candidate_num = 2;
727 if (!rtcp_mux) {
728 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
729 // for rtp and rtcp.
730 expected_candidate_num = 4;
731 // Disable rtcp-mux from the answer
732
733 const std::string kRtcpMux = "a=rtcp-mux";
734 const std::string kXRtcpMux = "a=xrtcp-mux";
735 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
736 kXRtcpMux.c_str(), kXRtcpMux.length(),
737 &sdp);
738 }
739
740 SessionDescriptionInterface* new_answer = CreateSessionDescription(
741 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000742
743 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000744 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000745 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
746 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
747 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
748 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
749 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
750 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
751 if (bundle) {
752 EXPECT_TRUE(c0.IsEquivalent(c1));
753 } else {
754 EXPECT_FALSE(c0.IsEquivalent(c1));
755 }
756 }
757 }
758 // Tests that we can only send DTMF when the dtmf codec is supported.
759 void TestCanInsertDtmf(bool can) {
760 if (can) {
761 InitWithDtmfCodec();
762 } else {
763 Init();
764 }
765 mediastream_signaling_.SendAudioVideoStream1();
766 CreateAndSetRemoteOfferAndLocalAnswer();
767 EXPECT_FALSE(session_->CanInsertDtmf(""));
768 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
769 }
770
771 // The method sets up a call from the session to itself, in a loopback
772 // arrangement. It also uses a firewall rule to create a temporary
773 // disconnection. This code is placed as a method so that it can be invoked
774 // by multiple tests with different allocators (e.g. with and without BUNDLE).
775 // While running the call, this method also checks if the session goes through
776 // the correct sequence of ICE states when a connection is established,
777 // broken, and re-established.
778 // The Connection state should go:
779 // New -> Checking -> Connected -> Disconnected -> Connected.
780 // The Gathering state should go: New -> Gathering -> Completed.
781 void TestLoopbackCall() {
782 AddInterface(kClientAddr1);
783 Init();
784 mediastream_signaling_.SendAudioVideoStream1();
785 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
786
787 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
788 observer_.ice_gathering_state_);
789 SetLocalDescriptionWithoutError(offer);
790 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
791 observer_.ice_connection_state_);
792 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
793 observer_.ice_gathering_state_,
794 kIceCandidatesTimeout);
795 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
796 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
797 observer_.ice_gathering_state_,
798 kIceCandidatesTimeout);
799
800 std::string sdp;
801 offer->ToString(&sdp);
802 SessionDescriptionInterface* desc =
803 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
804 ASSERT_TRUE(desc != NULL);
805 SetRemoteDescriptionWithoutError(desc);
806
807 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
808 observer_.ice_connection_state_,
809 kIceCandidatesTimeout);
810 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
811 observer_.ice_connection_state_,
812 kIceCandidatesTimeout);
813 // TODO(bemasc): EXPECT(Completed) once the details are standardized.
814
815 // Adding firewall rule to block ping requests, which should cause
816 // transport channel failure.
817 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
818 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
819 observer_.ice_connection_state_,
820 kIceCandidatesTimeout);
821
822 // Clearing the rules, session should move back to completed state.
823 fss_->ClearRules();
824 // Session is automatically calling OnSignalingReady after creation of
825 // new portallocator session which will allocate new set of candidates.
826
827 // TODO(bemasc): Change this to Completed once the details are standardized.
828 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
829 observer_.ice_connection_state_,
830 kIceCandidatesTimeout);
831 }
832
833 void VerifyTransportType(const std::string& content_name,
834 cricket::TransportProtocol protocol) {
835 const cricket::Transport* transport = session_->GetTransport(content_name);
836 ASSERT_TRUE(transport != NULL);
837 EXPECT_EQ(protocol, transport->protocol());
838 }
839
840 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
841 void AddCNCodecs() {
842 // Add kTelephoneEventCodec for dtmf test.
843 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
844 codecs.push_back(kCNCodec1);
845 codecs.push_back(kCNCodec2);
846 media_engine_->SetAudioCodecs(codecs);
847 desc_factory_->set_audio_codecs(codecs);
848 }
849
850 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
851 const cricket::ContentDescription* description = content->description;
852 ASSERT(description != NULL);
853 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000854 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855 ASSERT(audio_content_desc != NULL);
856 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
857 if (audio_content_desc->codecs()[i].name == "CN")
858 return false;
859 }
860 return true;
861 }
862
863 void SetLocalDescriptionWithDataChannel() {
864 webrtc::DataChannelInit dci;
865 dci.reliable = false;
866 session_->CreateDataChannel("datachannel", &dci);
867 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
868 SetLocalDescriptionWithoutError(offer);
869 }
870
871 cricket::FakeMediaEngine* media_engine_;
872 cricket::FakeDataEngine* data_engine_;
873 cricket::FakeDeviceManager* device_manager_;
874 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
875 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000876 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
878 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
879 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
880 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
881 talk_base::SocketServerScope ss_scope_;
882 cricket::TestStunServer stun_server_;
883 talk_base::FakeNetworkManager network_manager_;
884 cricket::BasicPortAllocator allocator_;
885 talk_base::scoped_ptr<FakeConstraints> constraints_;
886 FakeMediaStreamSignaling mediastream_signaling_;
887 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
888 MockIceObserver observer_;
889 cricket::FakeVideoMediaChannel* video_channel_;
890 cricket::FakeVoiceMediaChannel* voice_channel_;
891};
892
893TEST_F(WebRtcSessionTest, TestInitialize) {
894 Init();
895}
896
897TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
898 InitWithDtls();
899}
900
901TEST_F(WebRtcSessionTest, TestSessionCandidates) {
902 TestSessionCandidatesWithBundleRtcpMux(false, false);
903}
904
905// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
906// with rtcp-mux and/or bundle.
907TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
908 TestSessionCandidatesWithBundleRtcpMux(false, true);
909}
910
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
912 TestSessionCandidatesWithBundleRtcpMux(true, true);
913}
914
915TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
916 AddInterface(kClientAddr1);
917 AddInterface(kClientAddr2);
918 Init();
919 mediastream_signaling_.SendAudioVideoStream1();
920 InitiateCall();
921 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
922 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
923 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
924}
925
926TEST_F(WebRtcSessionTest, TestStunError) {
927 AddInterface(kClientAddr1);
928 AddInterface(kClientAddr2);
929 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
930 Init();
931 mediastream_signaling_.SendAudioVideoStream1();
932 InitiateCall();
933 // Since kClientAddr1 is blocked, not expecting stun candidates for it.
934 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
935 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
936 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
937}
938
939// Test creating offers and receive answers and make sure the
940// media engine creates the expected send and receive streams.
941TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
942 Init();
943 mediastream_signaling_.SendAudioVideoStream1();
944 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
945 const std::string session_id_orig = offer->session_id();
946 const std::string session_version_orig = offer->session_version();
947 SetLocalDescriptionWithoutError(offer);
948
949 mediastream_signaling_.SendAudioVideoStream2();
950 SessionDescriptionInterface* answer =
951 CreateRemoteAnswer(session_->local_description());
952 SetRemoteDescriptionWithoutError(answer);
953
954 video_channel_ = media_engine_->GetVideoChannel(0);
955 voice_channel_ = media_engine_->GetVoiceChannel(0);
956
957 ASSERT_EQ(1u, video_channel_->recv_streams().size());
958 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
959
960 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
961 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
962
963 ASSERT_EQ(1u, video_channel_->send_streams().size());
964 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
965 ASSERT_EQ(1u, voice_channel_->send_streams().size());
966 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
967
968 // Create new offer without send streams.
969 mediastream_signaling_.SendNothing();
970 offer = session_->CreateOffer(NULL);
971
972 // Verify the session id is the same and the session version is
973 // increased.
974 EXPECT_EQ(session_id_orig, offer->session_id());
975 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
976 talk_base::FromString<uint64>(offer->session_version()));
977
978 SetLocalDescriptionWithoutError(offer);
979
980 mediastream_signaling_.SendAudioVideoStream2();
981 answer = CreateRemoteAnswer(session_->local_description());
982 SetRemoteDescriptionWithoutError(answer);
983
984 EXPECT_EQ(0u, video_channel_->send_streams().size());
985 EXPECT_EQ(0u, voice_channel_->send_streams().size());
986
987 // Make sure the receive streams have not changed.
988 ASSERT_EQ(1u, video_channel_->recv_streams().size());
989 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
990 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
991 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
992}
993
994// Test receiving offers and creating answers and make sure the
995// media engine creates the expected send and receive streams.
996TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
997 Init();
998 mediastream_signaling_.SendAudioVideoStream2();
999 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1000 SetRemoteDescriptionWithoutError(offer);
1001
1002 mediastream_signaling_.SendAudioVideoStream1();
1003 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1004 SetLocalDescriptionWithoutError(answer);
1005
1006 const std::string session_id_orig = answer->session_id();
1007 const std::string session_version_orig = answer->session_version();
1008
1009 video_channel_ = media_engine_->GetVideoChannel(0);
1010 voice_channel_ = media_engine_->GetVoiceChannel(0);
1011
1012 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1013 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1014
1015 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1016 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1017
1018 ASSERT_EQ(1u, video_channel_->send_streams().size());
1019 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1020 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1021 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1022
1023 mediastream_signaling_.SendAudioVideoStream1And2();
1024 offer = session_->CreateOffer(NULL);
1025 SetRemoteDescriptionWithoutError(offer);
1026
1027 // Answer by turning off all send streams.
1028 mediastream_signaling_.SendNothing();
1029 answer = session_->CreateAnswer(NULL);
1030
1031 // Verify the session id is the same and the session version is
1032 // increased.
1033 EXPECT_EQ(session_id_orig, answer->session_id());
1034 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1035 talk_base::FromString<uint64>(answer->session_version()));
1036 SetLocalDescriptionWithoutError(answer);
1037
1038 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1039 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1040 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1041 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1042 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1043 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1044
1045 // Make sure we have no send streams.
1046 EXPECT_EQ(0u, video_channel_->send_streams().size());
1047 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1048}
1049
1050// Test we will return fail when apply an offer that doesn't have
1051// crypto enabled.
1052TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
1053 Init();
1054 cricket::MediaSessionOptions options;
1055 options.has_video = true;
1056 JsepSessionDescription* offer = CreateRemoteOffer(
1057 options, cricket::SEC_DISABLED);
1058 ASSERT_TRUE(offer != NULL);
1059 VerifyNoCryptoParams(offer->description(), false);
1060 // SetRemoteDescription and SetLocalDescription will take the ownership of
1061 // the offer.
1062 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
1063 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1064 ASSERT_TRUE(offer != NULL);
1065 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
1066}
1067
1068// Test we will return fail when apply an answer that doesn't have
1069// crypto enabled.
1070TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
1071 Init();
1072 SessionDescriptionInterface* offer = NULL;
1073 SessionDescriptionInterface* answer = NULL;
1074 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1075 // SetRemoteDescription and SetLocalDescription will take the ownership of
1076 // the offer.
1077 SetRemoteDescriptionWithoutError(offer);
1078 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
1079}
1080
1081// Test we will return fail when apply an answer that doesn't have
1082// crypto enabled.
1083TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
1084 Init();
1085 SessionDescriptionInterface* offer = NULL;
1086 SessionDescriptionInterface* answer = NULL;
1087 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1088 // SetRemoteDescription and SetLocalDescription will take the ownership of
1089 // the offer.
1090 SetLocalDescriptionWithoutError(offer);
1091 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
1092}
1093
1094// Test that we can create and set an offer with a DTLS fingerprint.
1095TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1096 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1097 InitWithDtls();
1098 mediastream_signaling_.SendAudioVideoStream1();
1099 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1100 ASSERT_TRUE(offer != NULL);
1101 VerifyFingerprintStatus(offer->description(), true);
1102 // SetLocalDescription will take the ownership of the offer.
1103 SetLocalDescriptionWithoutError(offer);
1104}
1105
1106// Test that we can process an offer with a DTLS fingerprint
1107// and that we return an answer with a fingerprint.
1108TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1109 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1110 InitWithDtls();
1111 SetFactoryDtlsSrtp();
1112 cricket::MediaSessionOptions options;
1113 options.has_video = true;
1114 JsepSessionDescription* offer = CreateRemoteOffer(options);
1115 ASSERT_TRUE(offer != NULL);
1116 VerifyFingerprintStatus(offer->description(), true);
1117
1118 // SetRemoteDescription will take the ownership of the offer.
1119 SetRemoteDescriptionWithoutError(offer);
1120
1121 // Verify that we get a crypto fingerprint in the answer.
1122 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1123 ASSERT_TRUE(answer != NULL);
1124 VerifyFingerprintStatus(answer->description(), true);
1125 // Check that we don't have an a=crypto line in the answer.
1126 VerifyNoCryptoParams(answer->description(), true);
1127
1128 // Now set the local description, which should work, even without a=crypto.
1129 SetLocalDescriptionWithoutError(answer);
1130}
1131
1132// Test that even if we support DTLS, if the other side didn't offer a
1133// fingerprint, we don't either.
1134TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1135 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1136 InitWithDtls();
1137 cricket::MediaSessionOptions options;
1138 options.has_video = true;
1139 JsepSessionDescription* offer = CreateRemoteOffer(
1140 options, cricket::SEC_REQUIRED);
1141 ASSERT_TRUE(offer != NULL);
1142 VerifyFingerprintStatus(offer->description(), false);
1143
1144 // SetRemoteDescription will take the ownership of
1145 // the offer.
1146 SetRemoteDescriptionWithoutError(offer);
1147
1148 // Verify that we don't get a crypto fingerprint in the answer.
1149 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1150 ASSERT_TRUE(answer != NULL);
1151 VerifyFingerprintStatus(answer->description(), false);
1152
1153 // Now set the local description.
1154 SetLocalDescriptionWithoutError(answer);
1155}
1156
1157TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
1158 Init();
1159 mediastream_signaling_.SendNothing();
1160 // SetLocalDescription take ownership of offer.
1161 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1162 SetLocalDescriptionWithoutError(offer);
1163
1164 // SetLocalDescription take ownership of offer.
1165 SessionDescriptionInterface* offer2 = session_->CreateOffer(NULL);
1166 SetLocalDescriptionWithoutError(offer2);
1167}
1168
1169TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
1170 Init();
1171 mediastream_signaling_.SendNothing();
1172 // SetLocalDescription take ownership of offer.
1173 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1174 SetRemoteDescriptionWithoutError(offer);
1175
1176 SessionDescriptionInterface* offer2 = session_->CreateOffer(NULL);
1177 SetRemoteDescriptionWithoutError(offer2);
1178}
1179
1180TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
1181 Init();
1182 mediastream_signaling_.SendNothing();
1183 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1184 SetLocalDescriptionWithoutError(offer);
1185 offer = session_->CreateOffer(NULL);
1186 SetRemoteDescriptionExpectError(
1187 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
1188 offer);
1189}
1190
1191TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
1192 Init();
1193 mediastream_signaling_.SendNothing();
1194 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1195 SetRemoteDescriptionWithoutError(offer);
1196 offer = session_->CreateOffer(NULL);
1197 SetLocalDescriptionExpectError(
1198 "Called with type in wrong state, type: "
1199 "offer state: STATE_RECEIVEDINITIATE",
1200 offer);
1201}
1202
1203TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
1204 Init();
1205 mediastream_signaling_.SendNothing();
1206 SessionDescriptionInterface* offer = CreateRemoteOffer();
1207 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1208
1209 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
1210 session_->CreateAnswer(NULL));
1211 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1212 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1213
1214 mediastream_signaling_.SendAudioVideoStream1();
1215 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
1216 session_->CreateAnswer(NULL));
1217 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1218
1219 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1220
1221 mediastream_signaling_.SendAudioVideoStream2();
1222 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1223 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1224}
1225
1226TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
1227 Init();
1228 mediastream_signaling_.SendNothing();
1229 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1230 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1231
1232 JsepSessionDescription* pranswer =
1233 CreateRemoteAnswer(session_->local_description());
1234 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1235
1236 SetRemoteDescriptionExpectState(pranswer,
1237 BaseSession::STATE_RECEIVEDPRACCEPT);
1238
1239 mediastream_signaling_.SendAudioVideoStream1();
1240 JsepSessionDescription* pranswer2 =
1241 CreateRemoteAnswer(session_->local_description());
1242 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1243
1244 SetRemoteDescriptionExpectState(pranswer2,
1245 BaseSession::STATE_RECEIVEDPRACCEPT);
1246
1247 mediastream_signaling_.SendAudioVideoStream2();
1248 SessionDescriptionInterface* answer =
1249 CreateRemoteAnswer(session_->local_description());
1250 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1251}
1252
1253TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
1254 Init();
1255 mediastream_signaling_.SendNothing();
1256 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1257 session_->CreateOffer(NULL));
1258 SessionDescriptionInterface* answer =
1259 CreateRemoteAnswer(offer.get());
1260 SetLocalDescriptionExpectError(
1261 "Called with type in wrong state, type: answer state: STATE_INIT",
1262 answer);
1263}
1264
1265TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
1266 Init();
1267 mediastream_signaling_.SendNothing();
1268 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1269 session_->CreateOffer(NULL));
1270 SessionDescriptionInterface* answer =
1271 CreateRemoteAnswer(offer.get());
1272 SetRemoteDescriptionExpectError(
1273 "Called with type in wrong state, type: answer state: STATE_INIT",
1274 answer);
1275}
1276
1277TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
1278 Init();
1279 mediastream_signaling_.SendAudioVideoStream1();
1280
1281 cricket::Candidate candidate;
1282 candidate.set_component(1);
1283 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1284
1285 // Fail since we have not set a offer description.
1286 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1287
1288 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1289 SetLocalDescriptionWithoutError(offer);
1290 // Candidate should be allowed to add before remote description.
1291 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1292 candidate.set_component(2);
1293 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1294 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1295
1296 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1297 session_->local_description());
1298 SetRemoteDescriptionWithoutError(answer);
1299
1300 // Verifying the candidates are copied properly from internal vector.
1301 const SessionDescriptionInterface* remote_desc =
1302 session_->remote_description();
1303 ASSERT_TRUE(remote_desc != NULL);
1304 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1305 const IceCandidateCollection* candidates =
1306 remote_desc->candidates(kMediaContentIndex0);
1307 ASSERT_EQ(2u, candidates->count());
1308 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1309 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1310 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1311 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1312
1313 candidate.set_component(2);
1314 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1315 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1316 ASSERT_EQ(3u, candidates->count());
1317
1318 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1319 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1320}
1321
1322// Test that a remote candidate is added to the remote session description and
1323// that it is retained if the remote session description is changed.
1324TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
1325 Init();
1326 cricket::Candidate candidate1;
1327 candidate1.set_component(1);
1328 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1329 candidate1);
1330 mediastream_signaling_.SendAudioVideoStream1();
1331 CreateAndSetRemoteOfferAndLocalAnswer();
1332
1333 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1334 const SessionDescriptionInterface* remote_desc =
1335 session_->remote_description();
1336 ASSERT_TRUE(remote_desc != NULL);
1337 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1338 const IceCandidateCollection* candidates =
1339 remote_desc->candidates(kMediaContentIndex0);
1340 ASSERT_EQ(1u, candidates->count());
1341 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1342
1343 // Update the RemoteSessionDescription with a new session description and
1344 // a candidate and check that the new remote session description contains both
1345 // candidates.
1346 SessionDescriptionInterface* offer = CreateRemoteOffer();
1347 cricket::Candidate candidate2;
1348 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1349 candidate2);
1350 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1351 SetRemoteDescriptionWithoutError(offer);
1352
1353 remote_desc = session_->remote_description();
1354 ASSERT_TRUE(remote_desc != NULL);
1355 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1356 candidates = remote_desc->candidates(kMediaContentIndex0);
1357 ASSERT_EQ(2u, candidates->count());
1358 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1359 // Username and password have be updated with the TransportInfo of the
1360 // SessionDescription, won't be equal to the original one.
1361 candidate2.set_username(candidates->at(0)->candidate().username());
1362 candidate2.set_password(candidates->at(0)->candidate().password());
1363 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1364 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1365 // No need to verify the username and password.
1366 candidate1.set_username(candidates->at(1)->candidate().username());
1367 candidate1.set_password(candidates->at(1)->candidate().password());
1368 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1369
1370 // Test that the candidate is ignored if we can add the same candidate again.
1371 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1372}
1373
1374// Test that local candidates are added to the local session description and
1375// that they are retained if the local session description is changed.
1376TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1377 AddInterface(kClientAddr1);
1378 Init();
1379 mediastream_signaling_.SendAudioVideoStream1();
1380 CreateAndSetRemoteOfferAndLocalAnswer();
1381
1382 const SessionDescriptionInterface* local_desc = session_->local_description();
1383 const IceCandidateCollection* candidates =
1384 local_desc->candidates(kMediaContentIndex0);
1385 ASSERT_TRUE(candidates != NULL);
1386 EXPECT_EQ(0u, candidates->count());
1387
1388 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1389
1390 local_desc = session_->local_description();
1391 candidates = local_desc->candidates(kMediaContentIndex0);
1392 ASSERT_TRUE(candidates != NULL);
1393 EXPECT_LT(0u, candidates->count());
1394 candidates = local_desc->candidates(1);
1395 ASSERT_TRUE(candidates != NULL);
1396 EXPECT_LT(0u, candidates->count());
1397
1398 // Update the session descriptions.
1399 mediastream_signaling_.SendAudioVideoStream1();
1400 CreateAndSetRemoteOfferAndLocalAnswer();
1401
1402 local_desc = session_->local_description();
1403 candidates = local_desc->candidates(kMediaContentIndex0);
1404 ASSERT_TRUE(candidates != NULL);
1405 EXPECT_LT(0u, candidates->count());
1406 candidates = local_desc->candidates(1);
1407 ASSERT_TRUE(candidates != NULL);
1408 EXPECT_LT(0u, candidates->count());
1409}
1410
1411// Test that we can set a remote session description with remote candidates.
1412TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
1413 Init();
1414
1415 cricket::Candidate candidate1;
1416 candidate1.set_component(1);
1417 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1418 candidate1);
1419 mediastream_signaling_.SendAudioVideoStream1();
1420 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1421
1422 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1423 SetRemoteDescriptionWithoutError(offer);
1424
1425 const SessionDescriptionInterface* remote_desc =
1426 session_->remote_description();
1427 ASSERT_TRUE(remote_desc != NULL);
1428 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1429 const IceCandidateCollection* candidates =
1430 remote_desc->candidates(kMediaContentIndex0);
1431 ASSERT_EQ(1u, candidates->count());
1432 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1433
1434 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1435 SetLocalDescriptionWithoutError(answer);
1436}
1437
1438// Test that offers and answers contains ice candidates when Ice candidates have
1439// been gathered.
1440TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1441 AddInterface(kClientAddr1);
1442 Init();
1443 mediastream_signaling_.SendAudioVideoStream1();
1444 // Ice is started but candidates are not provided until SetLocalDescription
1445 // is called.
1446 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1447 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1448 CreateAndSetRemoteOfferAndLocalAnswer();
1449 // Wait until at least one local candidate has been collected.
1450 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1451 kIceCandidatesTimeout);
1452 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1453 kIceCandidatesTimeout);
1454
1455 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
1456 session_->CreateOffer(NULL));
1457 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1458 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1459 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1460 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1461
1462 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1463 SetRemoteDescriptionWithoutError(remote_offer);
1464 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
1465 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1466 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1467 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1468 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1469 SetLocalDescriptionWithoutError(answer);
1470}
1471
1472// Verifies TransportProxy and media channels are created with content names
1473// present in the SessionDescription.
1474TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
1475 Init();
1476 mediastream_signaling_.SendAudioVideoStream1();
1477 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1478 session_->CreateOffer(NULL));
1479
1480 // CreateOffer creates session description with the content names "audio" and
1481 // "video". Goal is to modify these content names and verify transport channel
1482 // proxy in the BaseSession, as proxies are created with the content names
1483 // present in SDP.
1484 std::string sdp;
1485 EXPECT_TRUE(offer->ToString(&sdp));
1486 const std::string kAudioMid = "a=mid:audio";
1487 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1488 const std::string kVideoMid = "a=mid:video";
1489 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1490
1491 // Replacing |audio| with |audio_content_name|.
1492 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1493 kAudioMidReplaceStr.c_str(),
1494 kAudioMidReplaceStr.length(),
1495 &sdp);
1496 // Replacing |video| with |video_content_name|.
1497 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1498 kVideoMidReplaceStr.c_str(),
1499 kVideoMidReplaceStr.length(),
1500 &sdp);
1501
1502 SessionDescriptionInterface* modified_offer =
1503 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1504
1505 SetRemoteDescriptionWithoutError(modified_offer);
1506
1507 SessionDescriptionInterface* answer =
1508 session_->CreateAnswer(NULL);
1509 SetLocalDescriptionWithoutError(answer);
1510
1511 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1512 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1513 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1514 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1515}
1516
1517// Test that an offer contains the correct media content descriptions based on
1518// the send streams when no constraints have been set.
1519TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
1520 Init();
1521 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1522 session_->CreateOffer(NULL));
1523 ASSERT_TRUE(offer != NULL);
1524 const cricket::ContentInfo* content =
1525 cricket::GetFirstAudioContent(offer->description());
1526 EXPECT_TRUE(content != NULL);
1527 content = cricket::GetFirstVideoContent(offer->description());
1528 EXPECT_TRUE(content == NULL);
1529}
1530
1531// Test that an offer contains the correct media content descriptions based on
1532// the send streams when no constraints have been set.
1533TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
1534 Init();
1535 // Test Audio only offer.
1536 mediastream_signaling_.UseOptionsAudioOnly();
1537 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1538 session_->CreateOffer(NULL));
1539 const cricket::ContentInfo* content =
1540 cricket::GetFirstAudioContent(offer->description());
1541 EXPECT_TRUE(content != NULL);
1542 content = cricket::GetFirstVideoContent(offer->description());
1543 EXPECT_TRUE(content == NULL);
1544
1545 // Test Audio / Video offer.
1546 mediastream_signaling_.SendAudioVideoStream1();
1547 offer.reset(session_->CreateOffer(NULL));
1548 content = cricket::GetFirstAudioContent(offer->description());
1549 EXPECT_TRUE(content != NULL);
1550 content = cricket::GetFirstVideoContent(offer->description());
1551 EXPECT_TRUE(content != NULL);
1552}
1553
1554// Test that an offer contains no media content descriptions if
1555// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1556TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
1557 Init();
1558 webrtc::FakeConstraints constraints_no_receive;
1559 constraints_no_receive.SetMandatoryReceiveAudio(false);
1560 constraints_no_receive.SetMandatoryReceiveVideo(false);
1561
1562 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1563 session_->CreateOffer(&constraints_no_receive));
1564 ASSERT_TRUE(offer != NULL);
1565 const cricket::ContentInfo* content =
1566 cricket::GetFirstAudioContent(offer->description());
1567 EXPECT_TRUE(content == NULL);
1568 content = cricket::GetFirstVideoContent(offer->description());
1569 EXPECT_TRUE(content == NULL);
1570}
1571
1572// Test that an offer contains only audio media content descriptions if
1573// kOfferToReceiveAudio constraints are set to true.
1574TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
1575 Init();
1576 webrtc::FakeConstraints constraints_audio_only;
1577 constraints_audio_only.SetMandatoryReceiveAudio(true);
1578 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1579 session_->CreateOffer(&constraints_audio_only));
1580
1581 const cricket::ContentInfo* content =
1582 cricket::GetFirstAudioContent(offer->description());
1583 EXPECT_TRUE(content != NULL);
1584 content = cricket::GetFirstVideoContent(offer->description());
1585 EXPECT_TRUE(content == NULL);
1586}
1587
1588// Test that an offer contains audio and video media content descriptions if
1589// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1590TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
1591 Init();
1592 // Test Audio / Video offer.
1593 webrtc::FakeConstraints constraints_audio_video;
1594 constraints_audio_video.SetMandatoryReceiveAudio(true);
1595 constraints_audio_video.SetMandatoryReceiveVideo(true);
1596 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1597 session_->CreateOffer(&constraints_audio_video));
1598 const cricket::ContentInfo* content =
1599 cricket::GetFirstAudioContent(offer->description());
1600
1601 EXPECT_TRUE(content != NULL);
1602 content = cricket::GetFirstVideoContent(offer->description());
1603 EXPECT_TRUE(content != NULL);
1604
1605 // TODO(perkj): Should the direction be set to SEND_ONLY if
1606 // The constraints is set to not receive audio or video but a track is added?
1607}
1608
1609// Test that an answer can not be created if the last remote description is not
1610// an offer.
1611TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
1612 Init();
1613 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1614 SetLocalDescriptionWithoutError(offer);
1615 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1616 SetRemoteDescriptionWithoutError(answer);
1617 EXPECT_TRUE(session_->CreateAnswer(NULL) == NULL);
1618}
1619
1620// Test that an answer contains the correct media content descriptions when no
1621// constraints have been set.
1622TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
1623 Init();
1624 // Create a remote offer with audio and video content.
1625 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1626 SetRemoteDescriptionWithoutError(offer.release());
1627 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1628 session_->CreateAnswer(NULL));
1629 const cricket::ContentInfo* content =
1630 cricket::GetFirstAudioContent(answer->description());
1631 ASSERT_TRUE(content != NULL);
1632 EXPECT_FALSE(content->rejected);
1633
1634 content = cricket::GetFirstVideoContent(answer->description());
1635 ASSERT_TRUE(content != NULL);
1636 EXPECT_FALSE(content->rejected);
1637}
1638
1639// Test that an answer contains the correct media content descriptions when no
1640// constraints have been set and the offer only contain audio.
1641TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
1642 Init();
1643 // Create a remote offer with audio only.
1644 cricket::MediaSessionOptions options;
1645 options.has_audio = true;
1646 options.has_video = false;
1647 talk_base::scoped_ptr<JsepSessionDescription> offer(
1648 CreateRemoteOffer(options));
1649 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1650 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1651
1652 SetRemoteDescriptionWithoutError(offer.release());
1653 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1654 session_->CreateAnswer(NULL));
1655 const cricket::ContentInfo* content =
1656 cricket::GetFirstAudioContent(answer->description());
1657 ASSERT_TRUE(content != NULL);
1658 EXPECT_FALSE(content->rejected);
1659
1660 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1661}
1662
1663// Test that an answer contains the correct media content descriptions when no
1664// constraints have been set.
1665TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
1666 Init();
1667 // Create a remote offer with audio and video content.
1668 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1669 SetRemoteDescriptionWithoutError(offer.release());
1670 // Test with a stream with tracks.
1671 mediastream_signaling_.SendAudioVideoStream1();
1672 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1673 session_->CreateAnswer(NULL));
1674 const cricket::ContentInfo* content =
1675 cricket::GetFirstAudioContent(answer->description());
1676 ASSERT_TRUE(content != NULL);
1677 EXPECT_FALSE(content->rejected);
1678
1679 content = cricket::GetFirstVideoContent(answer->description());
1680 ASSERT_TRUE(content != NULL);
1681 EXPECT_FALSE(content->rejected);
1682}
1683
1684// Test that an answer contains the correct media content descriptions when
1685// constraints have been set but no stream is sent.
1686TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
1687 Init();
1688 // Create a remote offer with audio and video content.
1689 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1690 SetRemoteDescriptionWithoutError(offer.release());
1691
1692 webrtc::FakeConstraints constraints_no_receive;
1693 constraints_no_receive.SetMandatoryReceiveAudio(false);
1694 constraints_no_receive.SetMandatoryReceiveVideo(false);
1695
1696 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1697 session_->CreateAnswer(&constraints_no_receive));
1698 const cricket::ContentInfo* content =
1699 cricket::GetFirstAudioContent(answer->description());
1700 ASSERT_TRUE(content != NULL);
1701 EXPECT_TRUE(content->rejected);
1702
1703 content = cricket::GetFirstVideoContent(answer->description());
1704 ASSERT_TRUE(content != NULL);
1705 EXPECT_TRUE(content->rejected);
1706}
1707
1708// Test that an answer contains the correct media content descriptions when
1709// constraints have been set and streams are sent.
1710TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
1711 Init();
1712 // Create a remote offer with audio and video content.
1713 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1714 SetRemoteDescriptionWithoutError(offer.release());
1715
1716 webrtc::FakeConstraints constraints_no_receive;
1717 constraints_no_receive.SetMandatoryReceiveAudio(false);
1718 constraints_no_receive.SetMandatoryReceiveVideo(false);
1719
1720 // Test with a stream with tracks.
1721 mediastream_signaling_.SendAudioVideoStream1();
1722 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1723 session_->CreateAnswer(&constraints_no_receive));
1724
1725 // TODO(perkj): Should the direction be set to SEND_ONLY?
1726 const cricket::ContentInfo* content =
1727 cricket::GetFirstAudioContent(answer->description());
1728 ASSERT_TRUE(content != NULL);
1729 EXPECT_FALSE(content->rejected);
1730
1731 // TODO(perkj): Should the direction be set to SEND_ONLY?
1732 content = cricket::GetFirstVideoContent(answer->description());
1733 ASSERT_TRUE(content != NULL);
1734 EXPECT_FALSE(content->rejected);
1735}
1736
1737TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1738 AddCNCodecs();
1739 Init();
1740 webrtc::FakeConstraints constraints;
1741 constraints.SetOptionalVAD(false);
1742 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1743 session_->CreateOffer(&constraints));
1744 const cricket::ContentInfo* content =
1745 cricket::GetFirstAudioContent(offer->description());
1746 EXPECT_TRUE(content != NULL);
1747 EXPECT_TRUE(VerifyNoCNCodecs(content));
1748}
1749
1750TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1751 AddCNCodecs();
1752 Init();
1753 // Create a remote offer with audio and video content.
1754 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1755 SetRemoteDescriptionWithoutError(offer.release());
1756
1757 webrtc::FakeConstraints constraints;
1758 constraints.SetOptionalVAD(false);
1759 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1760 session_->CreateAnswer(&constraints));
1761 const cricket::ContentInfo* content =
1762 cricket::GetFirstAudioContent(answer->description());
1763 ASSERT_TRUE(content != NULL);
1764 EXPECT_TRUE(VerifyNoCNCodecs(content));
1765}
1766
1767// This test verifies the call setup when remote answer with audio only and
1768// later updates with video.
1769TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
1770 Init();
1771 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1772 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1773
1774 mediastream_signaling_.SendAudioVideoStream1();
1775 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1776
1777 cricket::MediaSessionOptions options;
1778 options.has_video = false;
1779 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1780
1781 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1782 // and answer;
1783 SetLocalDescriptionWithoutError(offer);
1784 SetRemoteDescriptionWithoutError(answer);
1785
1786 video_channel_ = media_engine_->GetVideoChannel(0);
1787 voice_channel_ = media_engine_->GetVoiceChannel(0);
1788
1789 ASSERT_TRUE(video_channel_ == NULL);
1790
1791 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1792 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1793 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1794
1795 // Let the remote end update the session descriptions, with Audio and Video.
1796 mediastream_signaling_.SendAudioVideoStream2();
1797 CreateAndSetRemoteOfferAndLocalAnswer();
1798
1799 video_channel_ = media_engine_->GetVideoChannel(0);
1800 voice_channel_ = media_engine_->GetVoiceChannel(0);
1801
1802 ASSERT_TRUE(video_channel_ != NULL);
1803 ASSERT_TRUE(voice_channel_ != NULL);
1804
1805 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1806 ASSERT_EQ(1u, video_channel_->send_streams().size());
1807 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1808 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1809 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1810 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1811 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1812 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1813
1814 // Change session back to audio only.
1815 mediastream_signaling_.UseOptionsAudioOnly();
1816 CreateAndSetRemoteOfferAndLocalAnswer();
1817
1818 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1819 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1820 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1821 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1822 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1823}
1824
1825// This test verifies the call setup when remote answer with video only and
1826// later updates with audio.
1827TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
1828 Init();
1829 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1830 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1831 mediastream_signaling_.SendAudioVideoStream1();
1832 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
1833
1834 cricket::MediaSessionOptions options;
1835 options.has_audio = false;
1836 options.has_video = true;
1837 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1838 offer, options, cricket::SEC_ENABLED);
1839
1840 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1841 // and answer.
1842 SetLocalDescriptionWithoutError(offer);
1843 SetRemoteDescriptionWithoutError(answer);
1844
1845 video_channel_ = media_engine_->GetVideoChannel(0);
1846 voice_channel_ = media_engine_->GetVoiceChannel(0);
1847
1848 ASSERT_TRUE(voice_channel_ == NULL);
1849 ASSERT_TRUE(video_channel_ != NULL);
1850
1851 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1852 ASSERT_EQ(1u, video_channel_->send_streams().size());
1853 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1854
1855 // Update the session descriptions, with Audio and Video.
1856 mediastream_signaling_.SendAudioVideoStream2();
1857 CreateAndSetRemoteOfferAndLocalAnswer();
1858
1859 voice_channel_ = media_engine_->GetVoiceChannel(0);
1860 ASSERT_TRUE(voice_channel_ != NULL);
1861
1862 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1863 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1864 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1865 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1866
1867 // Change session back to video only.
1868 mediastream_signaling_.UseOptionsVideoOnly();
1869 CreateAndSetRemoteOfferAndLocalAnswer();
1870
1871 video_channel_ = media_engine_->GetVideoChannel(0);
1872 voice_channel_ = media_engine_->GetVoiceChannel(0);
1873
1874 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1875 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1876 ASSERT_EQ(1u, video_channel_->send_streams().size());
1877 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1878}
1879
1880TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
1881 Init();
1882 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
1883}
1884
1885TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
1886 Init();
1887 mediastream_signaling_.SendAudioVideoStream1();
1888 scoped_ptr<SessionDescriptionInterface> offer(
1889 session_->CreateOffer(NULL));
1890 VerifyCryptoParams(offer->description());
1891 SetRemoteDescriptionWithoutError(offer.release());
henrike@webrtc.org723d6832013-07-12 16:04:50 +00001892 scoped_ptr<SessionDescriptionInterface> answer(
1893 session_->CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001894 VerifyCryptoParams(answer->description());
1895}
1896
1897TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
1898 Init();
1899 session_->set_secure_policy(cricket::SEC_DISABLED);
1900 mediastream_signaling_.SendAudioVideoStream1();
1901 scoped_ptr<SessionDescriptionInterface> offer(
1902 session_->CreateOffer(NULL));
1903 VerifyNoCryptoParams(offer->description(), false);
1904}
1905
1906TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
1907 Init();
1908 VerifyAnswerFromNonCryptoOffer();
1909}
1910
1911TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
1912 Init();
1913 VerifyAnswerFromCryptoOffer();
1914}
1915
1916TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
1917 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
1918 // local description is removed by the application, BUNDLE flag should be
1919 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
1920 Init();
1921 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1922 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1923 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
1924 session_->CreateOffer(NULL));
1925 cricket::SessionDescription* offer_copy =
1926 offer->description()->Copy();
1927 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1928 JsepSessionDescription* modified_offer =
1929 new JsepSessionDescription(JsepSessionDescription::kOffer);
1930 modified_offer->Initialize(offer_copy, "1", "1");
1931
1932 SetLocalDescriptionWithoutError(modified_offer);
1933 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1934}
1935
1936TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
1937 Init();
1938 mediastream_signaling_.SendAudioVideoStream1();
1939 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1940 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1941 FakeConstraints constraints;
1942 constraints.SetMandatoryUseRtpMux(true);
1943 SessionDescriptionInterface* offer = session_->CreateOffer(&constraints);
1944 SetLocalDescriptionWithoutError(offer);
1945 mediastream_signaling_.SendAudioVideoStream2();
1946 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1947 CreateRemoteAnswer(session_->local_description()));
1948 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1949 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1950 JsepSessionDescription* modified_answer =
1951 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1952 modified_answer->Initialize(answer_copy, "1", "1");
1953 SetRemoteDescriptionWithoutError(modified_answer);
1954 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1955 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1956
1957 video_channel_ = media_engine_->GetVideoChannel(0);
1958 voice_channel_ = media_engine_->GetVoiceChannel(0);
1959
1960 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1961 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1962
1963 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1964 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1965
1966 ASSERT_EQ(1u, video_channel_->send_streams().size());
1967 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1968 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1969 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1970}
1971
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001972// This test verifies that SetLocalDescription and SetRemoteDescription fails
1973// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1974TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
1975 WebRtcSessionTest::Init();
1976 mediastream_signaling_.SendAudioVideoStream1();
1977 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1978 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1979 FakeConstraints constraints;
1980 constraints.SetMandatoryUseRtpMux(true);
1981 SessionDescriptionInterface* offer = session_->CreateOffer(&constraints);
1982 std::string offer_str;
1983 offer->ToString(&offer_str);
1984 // Disable rtcp-mux
1985 const std::string rtcp_mux = "rtcp-mux";
1986 const std::string xrtcp_mux = "xrtcp-mux";
1987 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1988 xrtcp_mux.c_str(), xrtcp_mux.length(),
1989 &offer_str);
1990 JsepSessionDescription *local_offer =
1991 new JsepSessionDescription(JsepSessionDescription::kOffer);
1992 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
1993 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
1994 JsepSessionDescription *remote_offer =
1995 new JsepSessionDescription(JsepSessionDescription::kOffer);
1996 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
1997 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
1998 // Trying unmodified SDP.
1999 SetLocalDescriptionWithoutError(offer);
2000}
2001
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002002TEST_F(WebRtcSessionTest, SetAudioPlayout) {
2003 Init();
2004 mediastream_signaling_.SendAudioVideoStream1();
2005 CreateAndSetRemoteOfferAndLocalAnswer();
2006 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2007 ASSERT_TRUE(channel != NULL);
2008 ASSERT_EQ(1u, channel->recv_streams().size());
2009 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2010 double left_vol, right_vol;
2011 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2012 EXPECT_EQ(1, left_vol);
2013 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002014 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2015 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2017 EXPECT_EQ(0, left_vol);
2018 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002019 EXPECT_EQ(0, renderer->channel_id());
2020 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2022 EXPECT_EQ(1, left_vol);
2023 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002024 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025}
2026
2027TEST_F(WebRtcSessionTest, SetAudioSend) {
2028 Init();
2029 mediastream_signaling_.SendAudioVideoStream1();
2030 CreateAndSetRemoteOfferAndLocalAnswer();
2031 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2032 ASSERT_TRUE(channel != NULL);
2033 ASSERT_EQ(1u, channel->send_streams().size());
2034 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2035 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2036
2037 cricket::AudioOptions options;
2038 options.echo_cancellation.Set(true);
2039
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002040 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2041 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002042 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2043 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002044 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002045
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002046 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002047 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2048 bool value;
2049 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2050 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002051 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052}
2053
2054TEST_F(WebRtcSessionTest, SetVideoPlayout) {
2055 Init();
2056 mediastream_signaling_.SendAudioVideoStream1();
2057 CreateAndSetRemoteOfferAndLocalAnswer();
2058 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2059 ASSERT_TRUE(channel != NULL);
2060 ASSERT_LT(0u, channel->renderers().size());
2061 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2062 ASSERT_EQ(1u, channel->recv_streams().size());
2063 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2064 cricket::FakeVideoRenderer renderer;
2065 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2066 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2067 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2068 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2069}
2070
2071TEST_F(WebRtcSessionTest, SetVideoSend) {
2072 Init();
2073 mediastream_signaling_.SendAudioVideoStream1();
2074 CreateAndSetRemoteOfferAndLocalAnswer();
2075 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2076 ASSERT_TRUE(channel != NULL);
2077 ASSERT_EQ(1u, channel->send_streams().size());
2078 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2079 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2080 cricket::VideoOptions* options = NULL;
2081 session_->SetVideoSend(send_ssrc, false, options);
2082 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2083 session_->SetVideoSend(send_ssrc, true, options);
2084 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2085}
2086
2087TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2088 TestCanInsertDtmf(false);
2089}
2090
2091TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2092 TestCanInsertDtmf(true);
2093}
2094
2095TEST_F(WebRtcSessionTest, InsertDtmf) {
2096 // Setup
2097 Init();
2098 mediastream_signaling_.SendAudioVideoStream1();
2099 CreateAndSetRemoteOfferAndLocalAnswer();
2100 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2101 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2102
2103 // Insert DTMF
2104 const int expected_flags = DF_SEND;
2105 const int expected_duration = 90;
2106 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2107 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2108 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2109
2110 // Verify
2111 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2112 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2113 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2114 expected_duration, expected_flags));
2115 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2116 expected_duration, expected_flags));
2117 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2118 expected_duration, expected_flags));
2119}
2120
2121// This test verifies the |initiator| flag when session initiates the call.
2122TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
2123 Init();
2124 EXPECT_FALSE(session_->initiator());
2125 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2126 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2127 SetLocalDescriptionWithoutError(offer);
2128 EXPECT_TRUE(session_->initiator());
2129 SetRemoteDescriptionWithoutError(answer);
2130 EXPECT_TRUE(session_->initiator());
2131}
2132
2133// This test verifies the |initiator| flag when session receives the call.
2134TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
2135 Init();
2136 EXPECT_FALSE(session_->initiator());
2137 SessionDescriptionInterface* offer = CreateRemoteOffer();
2138 SetRemoteDescriptionWithoutError(offer);
2139 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
2140
2141 EXPECT_FALSE(session_->initiator());
2142 SetLocalDescriptionWithoutError(answer);
2143 EXPECT_FALSE(session_->initiator());
2144}
2145
2146// This test verifies the ice protocol type at initiator of the call
2147// if |a=ice-options:google-ice| is present in answer.
2148TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
2149 Init();
2150 mediastream_signaling_.SendAudioVideoStream1();
2151 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002152 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2153 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002154 SetLocalDescriptionWithoutError(offer);
2155 std::string sdp;
2156 EXPECT_TRUE(answer->ToString(&sdp));
2157 // Adding ice-options to the session level.
2158 InjectAfter("t=0 0\r\n",
2159 "a=ice-options:google-ice\r\n",
2160 &sdp);
2161 SessionDescriptionInterface* answer_with_gice =
2162 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2163 SetRemoteDescriptionWithoutError(answer_with_gice);
2164 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2165 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2166}
2167
2168// This test verifies the ice protocol type at initiator of the call
2169// if ICE RFC5245 is supported in answer.
2170TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
2171 Init();
2172 mediastream_signaling_.SendAudioVideoStream1();
2173 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2174 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2175 SetLocalDescriptionWithoutError(offer);
2176
2177 SetRemoteDescriptionWithoutError(answer);
2178 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2179 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2180}
2181
2182// This test verifies the ice protocol type at receiver side of the call if
2183// receiver decides to use google-ice.
2184TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
2185 Init();
2186 mediastream_signaling_.SendAudioVideoStream1();
2187 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2188 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002189 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2190 session_->CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002191 std::string sdp;
2192 EXPECT_TRUE(answer->ToString(&sdp));
2193 // Adding ice-options to the session level.
2194 InjectAfter("t=0 0\r\n",
2195 "a=ice-options:google-ice\r\n",
2196 &sdp);
2197 SessionDescriptionInterface* answer_with_gice =
2198 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2199 SetLocalDescriptionWithoutError(answer_with_gice);
2200 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2201 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2202}
2203
2204// This test verifies the ice protocol type at receiver side of the call if
2205// receiver decides to use ice RFC 5245.
2206TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
2207 Init();
2208 mediastream_signaling_.SendAudioVideoStream1();
2209 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2210 SetRemoteDescriptionWithoutError(offer);
2211 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
2212 SetLocalDescriptionWithoutError(answer);
2213 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2214 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2215}
2216
2217// This test verifies the session state when ICE RFC5245 in offer and
2218// ICE google-ice in answer.
2219TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
2220 Init();
2221 mediastream_signaling_.SendAudioVideoStream1();
2222 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2223 session_->CreateOffer(NULL));
2224 std::string offer_str;
2225 offer->ToString(&offer_str);
2226 // Disable google-ice
2227 const std::string gice_option = "google-ice";
2228 const std::string xgoogle_xice = "xgoogle-xice";
2229 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2230 xgoogle_xice.c_str(), xgoogle_xice.length(),
2231 &offer_str);
2232 JsepSessionDescription *ice_only_offer =
2233 new JsepSessionDescription(JsepSessionDescription::kOffer);
2234 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2235 SetLocalDescriptionWithoutError(ice_only_offer);
2236 std::string original_offer_sdp;
2237 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002238 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002240 original_offer_sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002241 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002242 pranswer_with_gice);
2243 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002244 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002245 original_offer_sdp, NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002246 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002247 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248}
2249
2250// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2251TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
2252 Init();
2253 mediastream_signaling_.SendAudioVideoStream1();
2254 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2255 SetLocalDescriptionWithoutError(offer);
2256 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2257 CreateRemoteAnswer(session_->local_description()));
2258
2259 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2260 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002261 JsepSessionDescription* modified_answer =
2262 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002263
2264 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2265 answer->session_id(),
2266 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002267 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268
2269 // Modifying content names.
2270 std::string sdp;
2271 EXPECT_TRUE(answer->ToString(&sdp));
2272 const std::string kAudioMid = "a=mid:audio";
2273 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2274
2275 // Replacing |audio| with |audio_content_name|.
2276 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2277 kAudioMidReplaceStr.c_str(),
2278 kAudioMidReplaceStr.length(),
2279 &sdp);
2280
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002281 SessionDescriptionInterface* modified_answer1 =
2282 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2283 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002284
2285 SetRemoteDescriptionWithoutError(answer.release());
2286}
2287
2288// Verifying remote offer and local answer have matching m-lines as per
2289// RFC 3264.
2290TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
2291 Init();
2292 mediastream_signaling_.SendAudioVideoStream1();
2293 SessionDescriptionInterface* offer = CreateRemoteOffer();
2294 SetRemoteDescriptionWithoutError(offer);
2295 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
2296
2297 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2298 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002299 JsepSessionDescription* modified_answer =
2300 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002301
2302 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2303 answer->session_id(),
2304 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002305 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002306 SetLocalDescriptionWithoutError(answer);
2307}
2308
2309// This test verifies that WebRtcSession does not start candidate allocation
2310// before SetLocalDescription is called.
2311TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
2312 Init();
2313 mediastream_signaling_.SendAudioVideoStream1();
2314 SessionDescriptionInterface* offer = CreateRemoteOffer();
2315 cricket::Candidate candidate;
2316 candidate.set_component(1);
2317 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2318 candidate);
2319 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2320 cricket::Candidate candidate1;
2321 candidate1.set_component(1);
2322 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2323 candidate1);
2324 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2325 SetRemoteDescriptionWithoutError(offer);
2326 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2327 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2328
2329 // Pump for 1 second and verify that no candidates are generated.
2330 talk_base::Thread::Current()->ProcessMessages(1000);
2331 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2332 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2333
2334 SessionDescriptionInterface* answer = session_->CreateAnswer(NULL);
2335 SetLocalDescriptionWithoutError(answer);
2336 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2337 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2338 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2339}
2340
2341// This test verifies that crypto parameter is updated in local session
2342// description as per security policy set in MediaSessionDescriptionFactory.
2343TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
2344 Init();
2345 mediastream_signaling_.SendAudioVideoStream1();
2346 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2347 session_->CreateOffer(NULL));
2348
2349 // Making sure SetLocalDescription correctly sets crypto value in
2350 // SessionDescription object after de-serialization of sdp string. The value
2351 // will be set as per MediaSessionDescriptionFactory.
2352 std::string offer_str;
2353 offer->ToString(&offer_str);
2354 SessionDescriptionInterface* jsep_offer_str =
2355 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2356 SetLocalDescriptionWithoutError(jsep_offer_str);
2357 EXPECT_TRUE(session_->voice_channel()->secure_required());
2358 EXPECT_TRUE(session_->video_channel()->secure_required());
2359}
2360
2361// This test verifies the crypto parameter when security is disabled.
2362TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
2363 Init();
2364 mediastream_signaling_.SendAudioVideoStream1();
2365 session_->set_secure_policy(cricket::SEC_DISABLED);
2366 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
2367 session_->CreateOffer(NULL));
2368
2369 // Making sure SetLocalDescription correctly sets crypto value in
2370 // SessionDescription object after de-serialization of sdp string. The value
2371 // will be set as per MediaSessionDescriptionFactory.
2372 std::string offer_str;
2373 offer->ToString(&offer_str);
2374 SessionDescriptionInterface *jsep_offer_str =
2375 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2376 SetLocalDescriptionWithoutError(jsep_offer_str);
2377 EXPECT_FALSE(session_->voice_channel()->secure_required());
2378 EXPECT_FALSE(session_->video_channel()->secure_required());
2379}
2380
2381// This test verifies that an answer contains new ufrag and password if an offer
2382// with new ufrag and password is received.
2383TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
2384 Init();
2385 cricket::MediaSessionOptions options;
2386 options.has_audio = true;
2387 options.has_video = true;
2388 talk_base::scoped_ptr<JsepSessionDescription> offer(
2389 CreateRemoteOffer(options));
2390 SetRemoteDescriptionWithoutError(offer.release());
2391
2392 mediastream_signaling_.SendAudioVideoStream1();
2393 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2394 session_->CreateAnswer(NULL));
2395 SetLocalDescriptionWithoutError(answer.release());
2396
2397 // Receive an offer with new ufrag and password.
2398 options.transport_options.ice_restart = true;
2399 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
2400 CreateRemoteOffer(options,
2401 session_->remote_description()));
2402 SetRemoteDescriptionWithoutError(updated_offer1.release());
2403
2404 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
2405 session_->CreateAnswer(NULL));
2406
2407 CompareIceUfragAndPassword(updated_answer1->description(),
2408 session_->local_description()->description(),
2409 false);
2410
2411 SetLocalDescriptionWithoutError(updated_answer1.release());
2412
2413 // Receive yet an offer without changed ufrag or password.
2414 options.transport_options.ice_restart = false;
2415 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
2416 CreateRemoteOffer(options,
2417 session_->remote_description()));
2418 SetRemoteDescriptionWithoutError(updated_offer2.release());
2419
2420 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
2421 session_->CreateAnswer(NULL));
2422
2423 CompareIceUfragAndPassword(updated_answer2->description(),
2424 session_->local_description()->description(),
2425 true);
2426
2427 SetLocalDescriptionWithoutError(updated_answer2.release());
2428}
2429
2430TEST_F(WebRtcSessionTest, TestSessionContentError) {
2431 Init();
2432 mediastream_signaling_.SendAudioVideoStream1();
2433 SessionDescriptionInterface* offer = session_->CreateOffer(NULL);
2434 const std::string session_id_orig = offer->session_id();
2435 const std::string session_version_orig = offer->session_version();
2436 SetLocalDescriptionWithoutError(offer);
2437
2438 video_channel_ = media_engine_->GetVideoChannel(0);
2439 video_channel_->set_fail_set_send_codecs(true);
2440
2441 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002442 SessionDescriptionInterface* answer =
2443 CreateRemoteAnswer(session_->local_description());
2444 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002445}
2446
2447// Runs the loopback call test with BUNDLE and STUN disabled.
2448TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2449 // Lets try with only UDP ports.
2450 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2451 cricket::PORTALLOCATOR_DISABLE_TCP |
2452 cricket::PORTALLOCATOR_DISABLE_STUN |
2453 cricket::PORTALLOCATOR_DISABLE_RELAY);
2454 TestLoopbackCall();
2455}
2456
2457// Regression-test for a crash which should have been an error.
2458TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
2459 Init();
2460 cricket::MediaSessionOptions options;
2461 options.has_audio = true;
2462 options.has_video = true;
2463
2464 session_->SetError(cricket::BaseSession::ERROR_CONTENT);
2465 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2466 SessionDescriptionInterface* answer =
2467 CreateRemoteAnswer(offer, options);
2468 SetRemoteDescriptionExpectError(kSessionError, offer);
2469 SetLocalDescriptionExpectError(kSessionError, answer);
2470 // Not crashing is our success.
2471}
2472
2473TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2474 constraints_.reset(new FakeConstraints());
2475 constraints_->AddOptional(
2476 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2477 Init();
2478
2479 SetLocalDescriptionWithDataChannel();
2480 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2481}
2482
2483TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2484 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2485
2486 constraints_.reset(new FakeConstraints());
2487 constraints_->AddOptional(
2488 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2489 constraints_->AddOptional(
2490 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2491 constraints_->AddOptional(
2492 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
2493 Init();
2494
2495 SetLocalDescriptionWithDataChannel();
2496 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2497}
2498
2499TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2500 constraints_.reset(new FakeConstraints());
2501 constraints_->AddOptional(
2502 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2503 Init();
2504
2505 SetLocalDescriptionWithDataChannel();
2506 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2507}
2508
2509TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2510 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2511
2512 constraints_.reset(new FakeConstraints());
2513 constraints_->AddOptional(
2514 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2515 constraints_->AddOptional(
2516 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
2517 Init();
2518
2519 SetLocalDescriptionWithDataChannel();
2520 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2521}
2522// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
2523// currently fails because upon disconnection and reconnection OnIceComplete is
2524// called more than once without returning to IceGatheringGathering.