blob: bcb209a0abef24edddeafa01c838e34b609b9883 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2012, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "talk/app/webrtc/audiotrack.h"
29#include "talk/app/webrtc/jsepicecandidate.h"
30#include "talk/app/webrtc/jsepsessiondescription.h"
31#include "talk/app/webrtc/mediastreamsignaling.h"
32#include "talk/app/webrtc/streamcollection.h"
33#include "talk/app/webrtc/videotrack.h"
34#include "talk/app/webrtc/test/fakeconstraints.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000035#include "talk/app/webrtc/test/fakedtlsidentityservice.h"
36#include "talk/app/webrtc/test/fakemediastreamsignaling.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/app/webrtc/webrtcsession.h"
wu@webrtc.org91053e72013-08-10 07:18:04 +000038#include "talk/app/webrtc/webrtcsessiondescriptionfactory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039#include "talk/base/fakenetwork.h"
40#include "talk/base/firewallsocketserver.h"
41#include "talk/base/gunit.h"
42#include "talk/base/logging.h"
43#include "talk/base/network.h"
44#include "talk/base/physicalsocketserver.h"
45#include "talk/base/sslstreamadapter.h"
46#include "talk/base/stringutils.h"
47#include "talk/base/thread.h"
48#include "talk/base/virtualsocketserver.h"
49#include "talk/media/base/fakemediaengine.h"
50#include "talk/media/base/fakevideorenderer.h"
51#include "talk/media/base/mediachannel.h"
52#include "talk/media/devices/fakedevicemanager.h"
53#include "talk/p2p/base/stunserver.h"
54#include "talk/p2p/base/teststunserver.h"
55#include "talk/p2p/client/basicportallocator.h"
56#include "talk/session/media/channelmanager.h"
57#include "talk/session/media/mediasession.h"
58
59#define MAYBE_SKIP_TEST(feature) \
60 if (!(feature())) { \
61 LOG(LS_INFO) << "Feature disabled... skipping"; \
62 return; \
63 }
64
65using cricket::BaseSession;
66using cricket::DF_PLAY;
67using cricket::DF_SEND;
68using cricket::FakeVoiceMediaChannel;
69using cricket::NS_GINGLE_P2P;
70using cricket::NS_JINGLE_ICE_UDP;
71using cricket::TransportInfo;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000072using talk_base::SocketAddress;
73using talk_base::scoped_ptr;
74using webrtc::CreateSessionDescription;
wu@webrtc.org91053e72013-08-10 07:18:04 +000075using webrtc::CreateSessionDescriptionObserver;
76using webrtc::CreateSessionDescriptionRequest;
77using webrtc::DTLSIdentityRequestObserver;
78using webrtc::DTLSIdentityServiceInterface;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079using webrtc::FakeConstraints;
80using webrtc::IceCandidateCollection;
81using webrtc::JsepIceCandidate;
82using webrtc::JsepSessionDescription;
83using webrtc::PeerConnectionInterface;
84using webrtc::SessionDescriptionInterface;
85using webrtc::StreamCollection;
wu@webrtc.org91053e72013-08-10 07:18:04 +000086using webrtc::WebRtcSession;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087using webrtc::kMlineMismatch;
88using webrtc::kSdpWithoutCrypto;
89using webrtc::kSessionError;
90using webrtc::kSetLocalSdpFailed;
91using webrtc::kSetRemoteSdpFailed;
92using webrtc::kPushDownAnswerTDFailed;
93using webrtc::kPushDownPranswerTDFailed;
henrike@webrtc.org1e09a712013-07-26 19:17:59 +000094using webrtc::kBundleWithoutRtcpMux;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095
96static const SocketAddress kClientAddr1("11.11.11.11", 0);
97static const SocketAddress kClientAddr2("22.22.22.22", 0);
98static const SocketAddress kStunAddr("99.99.99.1", cricket::STUN_SERVER_PORT);
99
100static const char kSessionVersion[] = "1";
101
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102// Media index of candidates belonging to the first media content.
103static const int kMediaContentIndex0 = 0;
104static const char kMediaContentName0[] = "audio";
105
106// Media index of candidates belonging to the second media content.
107static const int kMediaContentIndex1 = 1;
108static const char kMediaContentName1[] = "video";
109
110static const int kIceCandidatesTimeout = 10000;
111
112static const cricket::AudioCodec
113 kTelephoneEventCodec(106, "telephone-event", 8000, 0, 1, 0);
114static const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0);
115static const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0);
116
117// Add some extra |newlines| to the |message| after |line|.
118static void InjectAfter(const std::string& line,
119 const std::string& newlines,
120 std::string* message) {
121 const std::string tmp = line + newlines;
122 talk_base::replace_substrs(line.c_str(), line.length(),
123 tmp.c_str(), tmp.length(), message);
124}
125
126class MockIceObserver : public webrtc::IceObserver {
127 public:
128 MockIceObserver()
129 : oncandidatesready_(false),
130 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
131 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) {
132 }
133
134 virtual void OnIceConnectionChange(
135 PeerConnectionInterface::IceConnectionState new_state) {
136 ice_connection_state_ = new_state;
137 }
138 virtual void OnIceGatheringChange(
139 PeerConnectionInterface::IceGatheringState new_state) {
140 // We can never transition back to "new".
141 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state);
142 ice_gathering_state_ = new_state;
143
144 // oncandidatesready_ really means "ICE gathering is complete".
145 // This if statement ensures that this value remains correct when we
146 // transition from kIceGatheringComplete to kIceGatheringGathering.
147 if (new_state == PeerConnectionInterface::kIceGatheringGathering) {
148 oncandidatesready_ = false;
149 }
150 }
151
152 // Found a new candidate.
153 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
154 if (candidate->sdp_mline_index() == kMediaContentIndex0) {
155 mline_0_candidates_.push_back(candidate->candidate());
156 } else if (candidate->sdp_mline_index() == kMediaContentIndex1) {
157 mline_1_candidates_.push_back(candidate->candidate());
158 }
159 // The ICE gathering state should always be Gathering when a candidate is
160 // received (or possibly Completed in the case of the final candidate).
161 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_);
162 }
163
164 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange.
165 virtual void OnIceComplete() {
166 EXPECT_FALSE(oncandidatesready_);
167 oncandidatesready_ = true;
168
169 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should
170 // be called approximately simultaneously. For ease of testing, this
171 // check additionally requires that they be called in the above order.
172 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete,
173 ice_gathering_state_);
174 }
175
176 bool oncandidatesready_;
177 std::vector<cricket::Candidate> mline_0_candidates_;
178 std::vector<cricket::Candidate> mline_1_candidates_;
179 PeerConnectionInterface::IceConnectionState ice_connection_state_;
180 PeerConnectionInterface::IceGatheringState ice_gathering_state_;
181};
182
183class WebRtcSessionForTest : public webrtc::WebRtcSession {
184 public:
185 WebRtcSessionForTest(cricket::ChannelManager* cmgr,
186 talk_base::Thread* signaling_thread,
187 talk_base::Thread* worker_thread,
188 cricket::PortAllocator* port_allocator,
189 webrtc::IceObserver* ice_observer,
190 webrtc::MediaStreamSignaling* mediastream_signaling)
191 : WebRtcSession(cmgr, signaling_thread, worker_thread, port_allocator,
192 mediastream_signaling) {
193 RegisterIceObserver(ice_observer);
194 }
195 virtual ~WebRtcSessionForTest() {}
196
197 using cricket::BaseSession::GetTransportProxy;
198 using webrtc::WebRtcSession::SetAudioPlayout;
199 using webrtc::WebRtcSession::SetAudioSend;
200 using webrtc::WebRtcSession::SetCaptureDevice;
201 using webrtc::WebRtcSession::SetVideoPlayout;
202 using webrtc::WebRtcSession::SetVideoSend;
203};
204
wu@webrtc.org91053e72013-08-10 07:18:04 +0000205class WebRtcSessionCreateSDPObserverForTest
206 : public talk_base::RefCountedObject<CreateSessionDescriptionObserver> {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000207 public:
wu@webrtc.org91053e72013-08-10 07:18:04 +0000208 enum State {
209 kInit,
210 kFailed,
211 kSucceeded,
212 };
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000213 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {}
wu@webrtc.org91053e72013-08-10 07:18:04 +0000214
215 // CreateSessionDescriptionObserver implementation.
216 virtual void OnSuccess(SessionDescriptionInterface* desc) {
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000217 description_.reset(desc);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000218 state_ = kSucceeded;
219 }
220 virtual void OnFailure(const std::string& error) {
221 state_ = kFailed;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222 }
223
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000224 SessionDescriptionInterface* description() { return description_.get(); }
225
226 SessionDescriptionInterface* ReleaseDescription() {
227 return description_.release();
228 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229
wu@webrtc.org91053e72013-08-10 07:18:04 +0000230 State state() const { return state_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231
wu@webrtc.org91053e72013-08-10 07:18:04 +0000232 protected:
233 ~WebRtcSessionCreateSDPObserverForTest() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234
235 private:
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000236 talk_base::scoped_ptr<SessionDescriptionInterface> description_;
wu@webrtc.org91053e72013-08-10 07:18:04 +0000237 State state_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238};
239
henrike@webrtc.org1e09a712013-07-26 19:17:59 +0000240class FakeAudioRenderer : public cricket::AudioRenderer {
241 public:
242 FakeAudioRenderer() : channel_id_(-1) {}
243
244 virtual void AddChannel(int channel_id) OVERRIDE {
245 ASSERT(channel_id_ == -1);
246 channel_id_ = channel_id;
247 }
248 virtual void RemoveChannel(int channel_id) OVERRIDE {
249 ASSERT(channel_id == channel_id_);
250 channel_id_ = -1;
251 }
252
253 int channel_id() const { return channel_id_; }
254 private:
255 int channel_id_;
256};
257
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258class WebRtcSessionTest : public testing::Test {
259 protected:
260 // TODO Investigate why ChannelManager crashes, if it's created
261 // after stun_server.
262 WebRtcSessionTest()
263 : media_engine_(new cricket::FakeMediaEngine()),
264 data_engine_(new cricket::FakeDataEngine()),
265 device_manager_(new cricket::FakeDeviceManager()),
266 channel_manager_(new cricket::ChannelManager(
267 media_engine_, data_engine_, device_manager_,
268 new cricket::CaptureManager(), talk_base::Thread::Current())),
269 tdesc_factory_(new cricket::TransportDescriptionFactory()),
270 desc_factory_(new cricket::MediaSessionDescriptionFactory(
271 channel_manager_.get(), tdesc_factory_.get())),
272 pss_(new talk_base::PhysicalSocketServer),
273 vss_(new talk_base::VirtualSocketServer(pss_.get())),
274 fss_(new talk_base::FirewallSocketServer(vss_.get())),
275 ss_scope_(fss_.get()),
276 stun_server_(talk_base::Thread::Current(), kStunAddr),
277 allocator_(&network_manager_, kStunAddr,
278 SocketAddress(), SocketAddress(), SocketAddress()) {
279 tdesc_factory_->set_protocol(cricket::ICEPROTO_HYBRID);
280 allocator_.set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
281 cricket::PORTALLOCATOR_DISABLE_RELAY |
282 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
283 EXPECT_TRUE(channel_manager_->Init());
284 desc_factory_->set_add_legacy_streams(false);
285 }
286
287 void AddInterface(const SocketAddress& addr) {
288 network_manager_.AddInterface(addr);
289 }
290
wu@webrtc.org91053e72013-08-10 07:18:04 +0000291 void Init(DTLSIdentityServiceInterface* identity_service) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 ASSERT_TRUE(session_.get() == NULL);
293 session_.reset(new WebRtcSessionForTest(
294 channel_manager_.get(), talk_base::Thread::Current(),
295 talk_base::Thread::Current(), &allocator_,
296 &observer_,
297 &mediastream_signaling_));
298
299 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
300 observer_.ice_connection_state_);
301 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
302 observer_.ice_gathering_state_);
303
wu@webrtc.org91053e72013-08-10 07:18:04 +0000304 EXPECT_TRUE(session_->Initialize(constraints_.get(), identity_service));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000305 }
306
307 void InitWithDtmfCodec() {
308 // Add kTelephoneEventCodec for dtmf test.
309 std::vector<cricket::AudioCodec> codecs;
310 codecs.push_back(kTelephoneEventCodec);
311 media_engine_->SetAudioCodecs(codecs);
312 desc_factory_->set_audio_codecs(codecs);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000313 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 }
315
316 void InitWithDtls() {
317 constraints_.reset(new FakeConstraints());
318 constraints_->AddOptional(
319 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
320
wu@webrtc.org91053e72013-08-10 07:18:04 +0000321 Init(NULL);
322 }
323
324 void InitWithAsyncDtls(bool identity_request_should_fail) {
325 constraints_.reset(new FakeConstraints());
326 constraints_->AddOptional(
327 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
328 FakeIdentityService* identity_service = new FakeIdentityService();
329 identity_service->set_should_fail(identity_request_should_fail);
330 Init(identity_service);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000331 }
332
333 // Creates a local offer and applies it. Starts ice.
334 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
335 // to decide which streams to create.
336 void InitiateCall() {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000337 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338 SetLocalDescriptionWithoutError(offer);
339 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew !=
340 observer_.ice_gathering_state_,
341 kIceCandidatesTimeout);
342 }
343
wu@webrtc.org91053e72013-08-10 07:18:04 +0000344 SessionDescriptionInterface* CreateOffer(
345 const webrtc::MediaConstraintsInterface* constraints) {
346 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
347 observer = new WebRtcSessionCreateSDPObserverForTest();
348 session_->CreateOffer(observer, constraints);
349 EXPECT_TRUE_WAIT(
350 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
351 1000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000352 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000353 }
354
355 SessionDescriptionInterface* CreateAnswer(
356 const webrtc::MediaConstraintsInterface* constraints) {
357 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer
358 = new WebRtcSessionCreateSDPObserverForTest();
359 session_->CreateAnswer(observer, constraints);
360 EXPECT_TRUE_WAIT(
361 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
362 1000);
mallinath@webrtc.orga5506692013-08-12 21:18:15 +0000363 return observer->ReleaseDescription();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000364 }
365
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000366 bool ChannelsExist() {
367 return (session_->voice_channel() != NULL &&
368 session_->video_channel() != NULL);
369 }
370
371 void CheckTransportChannels() {
372 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 1) != NULL);
373 EXPECT_TRUE(session_->GetChannel(cricket::CN_AUDIO, 2) != NULL);
374 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 1) != NULL);
375 EXPECT_TRUE(session_->GetChannel(cricket::CN_VIDEO, 2) != NULL);
376 }
377
378 void VerifyCryptoParams(const cricket::SessionDescription* sdp) {
379 ASSERT_TRUE(session_.get() != NULL);
380 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
381 ASSERT_TRUE(content != NULL);
382 const cricket::AudioContentDescription* audio_content =
383 static_cast<const cricket::AudioContentDescription*>(
384 content->description);
385 ASSERT_TRUE(audio_content != NULL);
386 ASSERT_EQ(1U, audio_content->cryptos().size());
387 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size());
388 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
389 audio_content->cryptos()[0].cipher_suite);
390 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
391 audio_content->protocol());
392
393 content = cricket::GetFirstVideoContent(sdp);
394 ASSERT_TRUE(content != NULL);
395 const cricket::VideoContentDescription* video_content =
396 static_cast<const cricket::VideoContentDescription*>(
397 content->description);
398 ASSERT_TRUE(video_content != NULL);
399 ASSERT_EQ(1U, video_content->cryptos().size());
400 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80",
401 video_content->cryptos()[0].cipher_suite);
402 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size());
403 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
404 video_content->protocol());
405 }
406
407 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) {
408 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp);
409 ASSERT_TRUE(content != NULL);
410 const cricket::AudioContentDescription* audio_content =
411 static_cast<const cricket::AudioContentDescription*>(
412 content->description);
413 ASSERT_TRUE(audio_content != NULL);
414 ASSERT_EQ(0U, audio_content->cryptos().size());
415
416 content = cricket::GetFirstVideoContent(sdp);
417 ASSERT_TRUE(content != NULL);
418 const cricket::VideoContentDescription* video_content =
419 static_cast<const cricket::VideoContentDescription*>(
420 content->description);
421 ASSERT_TRUE(video_content != NULL);
422 ASSERT_EQ(0U, video_content->cryptos().size());
423
424 if (dtls) {
425 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
426 audio_content->protocol());
427 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
428 video_content->protocol());
429 } else {
430 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
431 audio_content->protocol());
432 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf),
433 video_content->protocol());
434 }
435 }
436
437 // Set the internal fake description factories to do DTLS-SRTP.
438 void SetFactoryDtlsSrtp() {
439 desc_factory_->set_secure(cricket::SEC_ENABLED);
440 std::string identity_name = "WebRTC" +
441 talk_base::ToString(talk_base::CreateRandomId());
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000442 identity_.reset(talk_base::SSLIdentity::Generate(identity_name));
443 tdesc_factory_->set_identity(identity_.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444 tdesc_factory_->set_digest_algorithm(talk_base::DIGEST_SHA_256);
445 tdesc_factory_->set_secure(cricket::SEC_REQUIRED);
446 }
447
448 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp,
449 bool expected) {
450 const TransportInfo* audio = sdp->GetTransportInfoByName("audio");
451 ASSERT_TRUE(audio != NULL);
452 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL);
453 if (expected) {
454 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), audio->description.
455 identity_fingerprint->algorithm);
456 }
457 const TransportInfo* video = sdp->GetTransportInfoByName("video");
458 ASSERT_TRUE(video != NULL);
459 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL);
460 if (expected) {
461 ASSERT_EQ(std::string(talk_base::DIGEST_SHA_256), video->description.
462 identity_fingerprint->algorithm);
463 }
464 }
465
466 void VerifyAnswerFromNonCryptoOffer() {
467 // Create a SDP without Crypto.
468 cricket::MediaSessionOptions options;
469 options.has_video = true;
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000470 JsepSessionDescription* offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000471 CreateRemoteOffer(options, cricket::SEC_DISABLED));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000472 ASSERT_TRUE(offer != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000473 VerifyNoCryptoParams(offer->description(), false);
474 SetRemoteDescriptionExpectError("Called with a SDP without crypto enabled",
wu@webrtc.org91053e72013-08-10 07:18:04 +0000475 offer);
476 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000477 // Answer should be NULL as no crypto params in offer.
478 ASSERT_TRUE(answer == NULL);
479 }
480
481 void VerifyAnswerFromCryptoOffer() {
482 cricket::MediaSessionOptions options;
483 options.has_video = true;
484 options.bundle_enabled = true;
485 scoped_ptr<JsepSessionDescription> offer(
486 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
487 ASSERT_TRUE(offer.get() != NULL);
488 VerifyCryptoParams(offer->description());
489 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +0000490 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000491 ASSERT_TRUE(answer.get() != NULL);
492 VerifyCryptoParams(answer->description());
493 }
494
495 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1,
496 const cricket::SessionDescription* desc2,
497 bool expect_equal) {
498 if (desc1->contents().size() != desc2->contents().size()) {
499 EXPECT_FALSE(expect_equal);
500 return;
501 }
502
503 const cricket::ContentInfos& contents = desc1->contents();
504 cricket::ContentInfos::const_iterator it = contents.begin();
505
506 for (; it != contents.end(); ++it) {
507 const cricket::TransportDescription* transport_desc1 =
508 desc1->GetTransportDescriptionByName(it->name);
509 const cricket::TransportDescription* transport_desc2 =
510 desc2->GetTransportDescriptionByName(it->name);
511 if (!transport_desc1 || !transport_desc2) {
512 EXPECT_FALSE(expect_equal);
513 return;
514 }
515 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd ||
516 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) {
517 EXPECT_FALSE(expect_equal);
518 return;
519 }
520 }
521 EXPECT_TRUE(expect_equal);
522 }
523 // Creates a remote offer and and applies it as a remote description,
524 // creates a local answer and applies is as a local description.
525 // Call mediastream_signaling_.UseOptionsWithStreamX() before this function
526 // to decide which local and remote streams to create.
527 void CreateAndSetRemoteOfferAndLocalAnswer() {
528 SessionDescriptionInterface* offer = CreateRemoteOffer();
529 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000530 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000531 SetLocalDescriptionWithoutError(answer);
532 }
533 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
534 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
535 }
536 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
537 BaseSession::State expected_state) {
538 SetLocalDescriptionWithoutError(desc);
539 EXPECT_EQ(expected_state, session_->state());
540 }
541 void SetLocalDescriptionExpectError(const std::string& expected_error,
542 SessionDescriptionInterface* desc) {
543 std::string error;
544 EXPECT_FALSE(session_->SetLocalDescription(desc, &error));
545 EXPECT_NE(std::string::npos, error.find(kSetLocalSdpFailed));
546 EXPECT_NE(std::string::npos, error.find(expected_error));
547 }
548 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
549 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
550 }
551 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
552 BaseSession::State expected_state) {
553 SetRemoteDescriptionWithoutError(desc);
554 EXPECT_EQ(expected_state, session_->state());
555 }
556 void SetRemoteDescriptionExpectError(const std::string& expected_error,
557 SessionDescriptionInterface* desc) {
558 std::string error;
559 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error));
560 EXPECT_NE(std::string::npos, error.find(kSetRemoteSdpFailed));
561 EXPECT_NE(std::string::npos, error.find(expected_error));
562 }
563
564 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer,
565 SessionDescriptionInterface** nocrypto_answer) {
566 // Create a SDP without Crypto.
567 cricket::MediaSessionOptions options;
568 options.has_video = true;
569 options.bundle_enabled = true;
570 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
571 ASSERT_TRUE(*offer != NULL);
572 VerifyCryptoParams((*offer)->description());
573
574 *nocrypto_answer = CreateRemoteAnswer(*offer, options,
575 cricket::SEC_DISABLED);
576 EXPECT_TRUE(*nocrypto_answer != NULL);
577 }
578
579 JsepSessionDescription* CreateRemoteOfferWithVersion(
580 cricket::MediaSessionOptions options,
581 cricket::SecurePolicy secure_policy,
582 const std::string& session_version,
583 const SessionDescriptionInterface* current_desc) {
584 std::string session_id = talk_base::ToString(talk_base::CreateRandomId64());
585 const cricket::SessionDescription* cricket_desc = NULL;
586 if (current_desc) {
587 cricket_desc = current_desc->description();
588 session_id = current_desc->session_id();
589 }
590
591 desc_factory_->set_secure(secure_policy);
592 JsepSessionDescription* offer(
593 new JsepSessionDescription(JsepSessionDescription::kOffer));
594 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc),
595 session_id, session_version)) {
596 delete offer;
597 offer = NULL;
598 }
599 return offer;
600 }
601 JsepSessionDescription* CreateRemoteOffer(
602 cricket::MediaSessionOptions options) {
603 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
604 kSessionVersion, NULL);
605 }
606 JsepSessionDescription* CreateRemoteOffer(
607 cricket::MediaSessionOptions options, cricket::SecurePolicy policy) {
608 return CreateRemoteOfferWithVersion(options, policy, kSessionVersion, NULL);
609 }
610 JsepSessionDescription* CreateRemoteOffer(
611 cricket::MediaSessionOptions options,
612 const SessionDescriptionInterface* current_desc) {
613 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED,
614 kSessionVersion, current_desc);
615 }
616
617 // Create a remote offer. Call mediastream_signaling_.UseOptionsWithStreamX()
618 // before this function to decide which streams to create.
619 JsepSessionDescription* CreateRemoteOffer() {
620 cricket::MediaSessionOptions options;
621 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
622 return CreateRemoteOffer(options, session_->remote_description());
623 }
624
625 JsepSessionDescription* CreateRemoteAnswer(
626 const SessionDescriptionInterface* offer,
627 cricket::MediaSessionOptions options,
628 cricket::SecurePolicy policy) {
629 desc_factory_->set_secure(policy);
630 const std::string session_id =
631 talk_base::ToString(talk_base::CreateRandomId64());
632 JsepSessionDescription* answer(
633 new JsepSessionDescription(JsepSessionDescription::kAnswer));
634 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(),
635 options, NULL),
636 session_id, kSessionVersion)) {
637 delete answer;
638 answer = NULL;
639 }
640 return answer;
641 }
642
643 JsepSessionDescription* CreateRemoteAnswer(
644 const SessionDescriptionInterface* offer,
645 cricket::MediaSessionOptions options) {
646 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
647 }
648
649 // Creates an answer session description with streams based on
650 // |mediastream_signaling_|. Call
651 // mediastream_signaling_.UseOptionsWithStreamX() before this function
652 // to decide which streams to create.
653 JsepSessionDescription* CreateRemoteAnswer(
654 const SessionDescriptionInterface* offer) {
655 cricket::MediaSessionOptions options;
656 mediastream_signaling_.GetOptionsForAnswer(NULL, &options);
657 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
658 }
659
660 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) {
661 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000662 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 mediastream_signaling_.SendAudioVideoStream1();
664 FakeConstraints constraints;
665 constraints.SetMandatoryUseRtpMux(bundle);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000666 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
668 // and answer.
669 SetLocalDescriptionWithoutError(offer);
670
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000671 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
672 CreateRemoteAnswer(session_->local_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000673 std::string sdp;
674 EXPECT_TRUE(answer->ToString(&sdp));
675
676 size_t expected_candidate_num = 2;
677 if (!rtcp_mux) {
678 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex
679 // for rtp and rtcp.
680 expected_candidate_num = 4;
681 // Disable rtcp-mux from the answer
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000682 const std::string kRtcpMux = "a=rtcp-mux";
683 const std::string kXRtcpMux = "a=xrtcp-mux";
684 talk_base::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(),
685 kXRtcpMux.c_str(), kXRtcpMux.length(),
686 &sdp);
687 }
688
689 SessionDescriptionInterface* new_answer = CreateSessionDescription(
690 JsepSessionDescription::kAnswer, sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691
692 // SetRemoteDescription to enable rtcp mux.
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000693 SetRemoteDescriptionWithoutError(new_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
695 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size());
696 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size());
697 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) {
698 cricket::Candidate c0 = observer_.mline_0_candidates_[i];
699 cricket::Candidate c1 = observer_.mline_1_candidates_[i];
700 if (bundle) {
701 EXPECT_TRUE(c0.IsEquivalent(c1));
702 } else {
703 EXPECT_FALSE(c0.IsEquivalent(c1));
704 }
705 }
706 }
707 // Tests that we can only send DTMF when the dtmf codec is supported.
708 void TestCanInsertDtmf(bool can) {
709 if (can) {
710 InitWithDtmfCodec();
711 } else {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000712 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000713 }
714 mediastream_signaling_.SendAudioVideoStream1();
715 CreateAndSetRemoteOfferAndLocalAnswer();
716 EXPECT_FALSE(session_->CanInsertDtmf(""));
717 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1));
718 }
719
720 // The method sets up a call from the session to itself, in a loopback
721 // arrangement. It also uses a firewall rule to create a temporary
722 // disconnection. This code is placed as a method so that it can be invoked
723 // by multiple tests with different allocators (e.g. with and without BUNDLE).
724 // While running the call, this method also checks if the session goes through
725 // the correct sequence of ICE states when a connection is established,
726 // broken, and re-established.
727 // The Connection state should go:
728 // New -> Checking -> Connected -> Disconnected -> Connected.
729 // The Gathering state should go: New -> Gathering -> Completed.
730 void TestLoopbackCall() {
731 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000732 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000733 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000734 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735
736 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew,
737 observer_.ice_gathering_state_);
738 SetLocalDescriptionWithoutError(offer);
739 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew,
740 observer_.ice_connection_state_);
741 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering,
742 observer_.ice_gathering_state_,
743 kIceCandidatesTimeout);
744 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
745 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete,
746 observer_.ice_gathering_state_,
747 kIceCandidatesTimeout);
748
749 std::string sdp;
750 offer->ToString(&sdp);
751 SessionDescriptionInterface* desc =
752 webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, sdp);
753 ASSERT_TRUE(desc != NULL);
754 SetRemoteDescriptionWithoutError(desc);
755
756 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking,
757 observer_.ice_connection_state_,
758 kIceCandidatesTimeout);
759 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
760 observer_.ice_connection_state_,
761 kIceCandidatesTimeout);
762 // TODO(bemasc): EXPECT(Completed) once the details are standardized.
763
764 // Adding firewall rule to block ping requests, which should cause
765 // transport channel failure.
766 fss_->AddRule(false, talk_base::FP_ANY, talk_base::FD_ANY, kClientAddr1);
767 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
768 observer_.ice_connection_state_,
769 kIceCandidatesTimeout);
770
771 // Clearing the rules, session should move back to completed state.
772 fss_->ClearRules();
773 // Session is automatically calling OnSignalingReady after creation of
774 // new portallocator session which will allocate new set of candidates.
775
776 // TODO(bemasc): Change this to Completed once the details are standardized.
777 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionConnected,
778 observer_.ice_connection_state_,
779 kIceCandidatesTimeout);
780 }
781
782 void VerifyTransportType(const std::string& content_name,
783 cricket::TransportProtocol protocol) {
784 const cricket::Transport* transport = session_->GetTransport(content_name);
785 ASSERT_TRUE(transport != NULL);
786 EXPECT_EQ(protocol, transport->protocol());
787 }
788
789 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory.
790 void AddCNCodecs() {
791 // Add kTelephoneEventCodec for dtmf test.
792 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();;
793 codecs.push_back(kCNCodec1);
794 codecs.push_back(kCNCodec2);
795 media_engine_->SetAudioCodecs(codecs);
796 desc_factory_->set_audio_codecs(codecs);
797 }
798
799 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
800 const cricket::ContentDescription* description = content->description;
801 ASSERT(description != NULL);
802 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000803 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000804 ASSERT(audio_content_desc != NULL);
805 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
806 if (audio_content_desc->codecs()[i].name == "CN")
807 return false;
808 }
809 return true;
810 }
811
812 void SetLocalDescriptionWithDataChannel() {
813 webrtc::DataChannelInit dci;
814 dci.reliable = false;
815 session_->CreateDataChannel("datachannel", &dci);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000816 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000817 SetLocalDescriptionWithoutError(offer);
818 }
819
wu@webrtc.org91053e72013-08-10 07:18:04 +0000820 void VerifyMultipleAsyncCreateDescription(
821 bool success, CreateSessionDescriptionRequest::Type type) {
822 InitWithAsyncDtls(!success);
823
824 if (type == CreateSessionDescriptionRequest::kAnswer) {
825 cricket::MediaSessionOptions options;
826 scoped_ptr<JsepSessionDescription> offer(
827 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
828 ASSERT_TRUE(offer.get() != NULL);
829 SetRemoteDescriptionWithoutError(offer.release());
830 }
831
832 const int kNumber = 3;
833 talk_base::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
834 observers[kNumber];
835 for (int i = 0; i < kNumber; ++i) {
836 observers[i] = new WebRtcSessionCreateSDPObserverForTest();
837 if (type == CreateSessionDescriptionRequest::kOffer) {
838 session_->CreateOffer(observers[i], NULL);
839 } else {
840 session_->CreateAnswer(observers[i], NULL);
841 }
842 }
843
844 WebRtcSessionCreateSDPObserverForTest::State expected_state =
845 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded :
846 WebRtcSessionCreateSDPObserverForTest::kFailed;
847
848 for (int i = 0; i < kNumber; ++i) {
849 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000);
850 if (success) {
851 EXPECT_TRUE(observers[i]->description() != NULL);
852 } else {
853 EXPECT_TRUE(observers[i]->description() == NULL);
854 }
855 }
856 }
857
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000858 cricket::FakeMediaEngine* media_engine_;
859 cricket::FakeDataEngine* data_engine_;
860 cricket::FakeDeviceManager* device_manager_;
861 talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
862 talk_base::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_;
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000863 talk_base::scoped_ptr<talk_base::SSLIdentity> identity_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 talk_base::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_;
865 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
866 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
867 talk_base::scoped_ptr<talk_base::FirewallSocketServer> fss_;
868 talk_base::SocketServerScope ss_scope_;
869 cricket::TestStunServer stun_server_;
870 talk_base::FakeNetworkManager network_manager_;
871 cricket::BasicPortAllocator allocator_;
872 talk_base::scoped_ptr<FakeConstraints> constraints_;
873 FakeMediaStreamSignaling mediastream_signaling_;
874 talk_base::scoped_ptr<WebRtcSessionForTest> session_;
875 MockIceObserver observer_;
876 cricket::FakeVideoMediaChannel* video_channel_;
877 cricket::FakeVoiceMediaChannel* voice_channel_;
878};
879
880TEST_F(WebRtcSessionTest, TestInitialize) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000881 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000882}
883
884TEST_F(WebRtcSessionTest, TestInitializeWithDtls) {
885 InitWithDtls();
886}
887
wu@webrtc.org91053e72013-08-10 07:18:04 +0000888// Verifies that WebRtcSession uses SEC_REQUIRED by default.
889TEST_F(WebRtcSessionTest, TestDefaultSetSecurePolicy) {
890 Init(NULL);
891 EXPECT_EQ(cricket::SEC_REQUIRED, session_->secure_policy());
892}
893
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894TEST_F(WebRtcSessionTest, TestSessionCandidates) {
895 TestSessionCandidatesWithBundleRtcpMux(false, false);
896}
897
898// Below test cases (TestSessionCandidatesWith*) verify the candidates gathered
899// with rtcp-mux and/or bundle.
900TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) {
901 TestSessionCandidatesWithBundleRtcpMux(false, true);
902}
903
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000904TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) {
905 TestSessionCandidatesWithBundleRtcpMux(true, true);
906}
907
908TEST_F(WebRtcSessionTest, TestMultihomeCandidates) {
909 AddInterface(kClientAddr1);
910 AddInterface(kClientAddr2);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000911 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000912 mediastream_signaling_.SendAudioVideoStream1();
913 InitiateCall();
914 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
915 EXPECT_EQ(8u, observer_.mline_0_candidates_.size());
916 EXPECT_EQ(8u, observer_.mline_1_candidates_.size());
917}
918
919TEST_F(WebRtcSessionTest, TestStunError) {
920 AddInterface(kClientAddr1);
921 AddInterface(kClientAddr2);
922 fss_->AddRule(false, talk_base::FP_UDP, talk_base::FD_ANY, kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +0000923 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000924 mediastream_signaling_.SendAudioVideoStream1();
925 InitiateCall();
926 // Since kClientAddr1 is blocked, not expecting stun candidates for it.
927 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
928 EXPECT_EQ(6u, observer_.mline_0_candidates_.size());
929 EXPECT_EQ(6u, observer_.mline_1_candidates_.size());
930}
931
932// Test creating offers and receive answers and make sure the
933// media engine creates the expected send and receive streams.
934TEST_F(WebRtcSessionTest, TestCreateOfferReceiveAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000935 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000936 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000937 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000938 const std::string session_id_orig = offer->session_id();
939 const std::string session_version_orig = offer->session_version();
940 SetLocalDescriptionWithoutError(offer);
941
942 mediastream_signaling_.SendAudioVideoStream2();
943 SessionDescriptionInterface* answer =
944 CreateRemoteAnswer(session_->local_description());
945 SetRemoteDescriptionWithoutError(answer);
946
947 video_channel_ = media_engine_->GetVideoChannel(0);
948 voice_channel_ = media_engine_->GetVoiceChannel(0);
949
950 ASSERT_EQ(1u, video_channel_->recv_streams().size());
951 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
952
953 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
954 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
955
956 ASSERT_EQ(1u, video_channel_->send_streams().size());
957 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
958 ASSERT_EQ(1u, voice_channel_->send_streams().size());
959 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
960
961 // Create new offer without send streams.
962 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000963 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000964
965 // Verify the session id is the same and the session version is
966 // increased.
967 EXPECT_EQ(session_id_orig, offer->session_id());
968 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
969 talk_base::FromString<uint64>(offer->session_version()));
970
971 SetLocalDescriptionWithoutError(offer);
972
973 mediastream_signaling_.SendAudioVideoStream2();
974 answer = CreateRemoteAnswer(session_->local_description());
975 SetRemoteDescriptionWithoutError(answer);
976
977 EXPECT_EQ(0u, video_channel_->send_streams().size());
978 EXPECT_EQ(0u, voice_channel_->send_streams().size());
979
980 // Make sure the receive streams have not changed.
981 ASSERT_EQ(1u, video_channel_->recv_streams().size());
982 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
983 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
984 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
985}
986
987// Test receiving offers and creating answers and make sure the
988// media engine creates the expected send and receive streams.
989TEST_F(WebRtcSessionTest, TestReceiveOfferCreateAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +0000990 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000991 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000992 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000993 SetRemoteDescriptionWithoutError(offer);
994
995 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +0000996 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 SetLocalDescriptionWithoutError(answer);
998
999 const std::string session_id_orig = answer->session_id();
1000 const std::string session_version_orig = answer->session_version();
1001
1002 video_channel_ = media_engine_->GetVideoChannel(0);
1003 voice_channel_ = media_engine_->GetVoiceChannel(0);
1004
1005 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1006 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1007
1008 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1009 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1010
1011 ASSERT_EQ(1u, video_channel_->send_streams().size());
1012 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1013 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1014 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1015
1016 mediastream_signaling_.SendAudioVideoStream1And2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001017 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 SetRemoteDescriptionWithoutError(offer);
1019
1020 // Answer by turning off all send streams.
1021 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001022 answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023
1024 // Verify the session id is the same and the session version is
1025 // increased.
1026 EXPECT_EQ(session_id_orig, answer->session_id());
1027 EXPECT_LT(talk_base::FromString<uint64>(session_version_orig),
1028 talk_base::FromString<uint64>(answer->session_version()));
1029 SetLocalDescriptionWithoutError(answer);
1030
1031 ASSERT_EQ(2u, video_channel_->recv_streams().size());
1032 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id);
1033 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id);
1034 ASSERT_EQ(2u, voice_channel_->recv_streams().size());
1035 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id);
1036 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id);
1037
1038 // Make sure we have no send streams.
1039 EXPECT_EQ(0u, video_channel_->send_streams().size());
1040 EXPECT_EQ(0u, voice_channel_->send_streams().size());
1041}
1042
1043// Test we will return fail when apply an offer that doesn't have
1044// crypto enabled.
1045TEST_F(WebRtcSessionTest, SetNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001046 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001047 cricket::MediaSessionOptions options;
1048 options.has_video = true;
1049 JsepSessionDescription* offer = CreateRemoteOffer(
1050 options, cricket::SEC_DISABLED);
1051 ASSERT_TRUE(offer != NULL);
1052 VerifyNoCryptoParams(offer->description(), false);
1053 // SetRemoteDescription and SetLocalDescription will take the ownership of
1054 // the offer.
1055 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, offer);
1056 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
1057 ASSERT_TRUE(offer != NULL);
1058 SetLocalDescriptionExpectError(kSdpWithoutCrypto, offer);
1059}
1060
1061// Test we will return fail when apply an answer that doesn't have
1062// crypto enabled.
1063TEST_F(WebRtcSessionTest, SetLocalNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001064 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001065 SessionDescriptionInterface* offer = NULL;
1066 SessionDescriptionInterface* answer = NULL;
1067 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1068 // SetRemoteDescription and SetLocalDescription will take the ownership of
1069 // the offer.
1070 SetRemoteDescriptionWithoutError(offer);
1071 SetLocalDescriptionExpectError(kSdpWithoutCrypto, answer);
1072}
1073
1074// Test we will return fail when apply an answer that doesn't have
1075// crypto enabled.
1076TEST_F(WebRtcSessionTest, SetRemoteNonCryptoAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001077 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001078 SessionDescriptionInterface* offer = NULL;
1079 SessionDescriptionInterface* answer = NULL;
1080 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer);
1081 // SetRemoteDescription and SetLocalDescription will take the ownership of
1082 // the offer.
1083 SetLocalDescriptionWithoutError(offer);
1084 SetRemoteDescriptionExpectError(kSdpWithoutCrypto, answer);
1085}
1086
1087// Test that we can create and set an offer with a DTLS fingerprint.
1088TEST_F(WebRtcSessionTest, CreateSetDtlsOffer) {
1089 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1090 InitWithDtls();
1091 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001092 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001093 ASSERT_TRUE(offer != NULL);
1094 VerifyFingerprintStatus(offer->description(), true);
1095 // SetLocalDescription will take the ownership of the offer.
1096 SetLocalDescriptionWithoutError(offer);
1097}
1098
1099// Test that we can process an offer with a DTLS fingerprint
1100// and that we return an answer with a fingerprint.
1101TEST_F(WebRtcSessionTest, ReceiveDtlsOfferCreateAnswer) {
1102 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1103 InitWithDtls();
1104 SetFactoryDtlsSrtp();
1105 cricket::MediaSessionOptions options;
1106 options.has_video = true;
1107 JsepSessionDescription* offer = CreateRemoteOffer(options);
1108 ASSERT_TRUE(offer != NULL);
1109 VerifyFingerprintStatus(offer->description(), true);
1110
1111 // SetRemoteDescription will take the ownership of the offer.
1112 SetRemoteDescriptionWithoutError(offer);
1113
1114 // Verify that we get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001115 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001116 ASSERT_TRUE(answer != NULL);
1117 VerifyFingerprintStatus(answer->description(), true);
1118 // Check that we don't have an a=crypto line in the answer.
1119 VerifyNoCryptoParams(answer->description(), true);
1120
1121 // Now set the local description, which should work, even without a=crypto.
1122 SetLocalDescriptionWithoutError(answer);
1123}
1124
1125// Test that even if we support DTLS, if the other side didn't offer a
1126// fingerprint, we don't either.
1127TEST_F(WebRtcSessionTest, ReceiveNoDtlsOfferCreateAnswer) {
1128 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
1129 InitWithDtls();
1130 cricket::MediaSessionOptions options;
1131 options.has_video = true;
1132 JsepSessionDescription* offer = CreateRemoteOffer(
1133 options, cricket::SEC_REQUIRED);
1134 ASSERT_TRUE(offer != NULL);
1135 VerifyFingerprintStatus(offer->description(), false);
1136
1137 // SetRemoteDescription will take the ownership of
1138 // the offer.
1139 SetRemoteDescriptionWithoutError(offer);
1140
1141 // Verify that we don't get a crypto fingerprint in the answer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001142 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001143 ASSERT_TRUE(answer != NULL);
1144 VerifyFingerprintStatus(answer->description(), false);
1145
1146 // Now set the local description.
1147 SetLocalDescriptionWithoutError(answer);
1148}
1149
1150TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001151 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 mediastream_signaling_.SendNothing();
1153 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001154 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001155 SetLocalDescriptionWithoutError(offer);
1156
1157 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001158 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001159 SetLocalDescriptionWithoutError(offer2);
1160}
1161
1162TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001163 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 mediastream_signaling_.SendNothing();
1165 // SetLocalDescription take ownership of offer.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001166 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001167 SetRemoteDescriptionWithoutError(offer);
1168
wu@webrtc.org91053e72013-08-10 07:18:04 +00001169 SessionDescriptionInterface* offer2 = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001170 SetRemoteDescriptionWithoutError(offer2);
1171}
1172
1173TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001174 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001176 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001177 SetLocalDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001178 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001179 SetRemoteDescriptionExpectError(
1180 "Called with type in wrong state, type: offer state: STATE_SENTINITIATE",
1181 offer);
1182}
1183
1184TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001185 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001186 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001187 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001189 offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190 SetLocalDescriptionExpectError(
1191 "Called with type in wrong state, type: "
1192 "offer state: STATE_RECEIVEDINITIATE",
1193 offer);
1194}
1195
1196TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001197 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198 mediastream_signaling_.SendNothing();
1199 SessionDescriptionInterface* offer = CreateRemoteOffer();
1200 SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
1201
1202 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001203 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1205 SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
1206
1207 mediastream_signaling_.SendAudioVideoStream1();
1208 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001209 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001210 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1211
1212 SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
1213
1214 mediastream_signaling_.SendAudioVideoStream2();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001215 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216 SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
1217}
1218
1219TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001220 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001221 mediastream_signaling_.SendNothing();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001222 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001223 SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
1224
1225 JsepSessionDescription* pranswer =
1226 CreateRemoteAnswer(session_->local_description());
1227 pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
1228
1229 SetRemoteDescriptionExpectState(pranswer,
1230 BaseSession::STATE_RECEIVEDPRACCEPT);
1231
1232 mediastream_signaling_.SendAudioVideoStream1();
1233 JsepSessionDescription* pranswer2 =
1234 CreateRemoteAnswer(session_->local_description());
1235 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
1236
1237 SetRemoteDescriptionExpectState(pranswer2,
1238 BaseSession::STATE_RECEIVEDPRACCEPT);
1239
1240 mediastream_signaling_.SendAudioVideoStream2();
1241 SessionDescriptionInterface* answer =
1242 CreateRemoteAnswer(session_->local_description());
1243 SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
1244}
1245
1246TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001247 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 mediastream_signaling_.SendNothing();
1249 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001250 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001251 SessionDescriptionInterface* answer =
1252 CreateRemoteAnswer(offer.get());
1253 SetLocalDescriptionExpectError(
1254 "Called with type in wrong state, type: answer state: STATE_INIT",
1255 answer);
1256}
1257
1258TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001259 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001260 mediastream_signaling_.SendNothing();
1261 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001262 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001263 SessionDescriptionInterface* answer =
1264 CreateRemoteAnswer(offer.get());
1265 SetRemoteDescriptionExpectError(
1266 "Called with type in wrong state, type: answer state: STATE_INIT",
1267 answer);
1268}
1269
1270TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001271 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 mediastream_signaling_.SendAudioVideoStream1();
1273
1274 cricket::Candidate candidate;
1275 candidate.set_component(1);
1276 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
1277
1278 // Fail since we have not set a offer description.
1279 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
1280
wu@webrtc.org91053e72013-08-10 07:18:04 +00001281 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001282 SetLocalDescriptionWithoutError(offer);
1283 // Candidate should be allowed to add before remote description.
1284 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1285 candidate.set_component(2);
1286 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
1287 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1288
1289 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1290 session_->local_description());
1291 SetRemoteDescriptionWithoutError(answer);
1292
1293 // Verifying the candidates are copied properly from internal vector.
1294 const SessionDescriptionInterface* remote_desc =
1295 session_->remote_description();
1296 ASSERT_TRUE(remote_desc != NULL);
1297 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1298 const IceCandidateCollection* candidates =
1299 remote_desc->candidates(kMediaContentIndex0);
1300 ASSERT_EQ(2u, candidates->count());
1301 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1302 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid());
1303 EXPECT_EQ(1, candidates->at(0)->candidate().component());
1304 EXPECT_EQ(2, candidates->at(1)->candidate().component());
1305
1306 candidate.set_component(2);
1307 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate);
1308 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3));
1309 ASSERT_EQ(3u, candidates->count());
1310
1311 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate);
1312 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate));
1313}
1314
1315// Test that a remote candidate is added to the remote session description and
1316// that it is retained if the remote session description is changed.
1317TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001318 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001319 cricket::Candidate candidate1;
1320 candidate1.set_component(1);
1321 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0,
1322 candidate1);
1323 mediastream_signaling_.SendAudioVideoStream1();
1324 CreateAndSetRemoteOfferAndLocalAnswer();
1325
1326 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
1327 const SessionDescriptionInterface* remote_desc =
1328 session_->remote_description();
1329 ASSERT_TRUE(remote_desc != NULL);
1330 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1331 const IceCandidateCollection* candidates =
1332 remote_desc->candidates(kMediaContentIndex0);
1333 ASSERT_EQ(1u, candidates->count());
1334 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1335
1336 // Update the RemoteSessionDescription with a new session description and
1337 // a candidate and check that the new remote session description contains both
1338 // candidates.
1339 SessionDescriptionInterface* offer = CreateRemoteOffer();
1340 cricket::Candidate candidate2;
1341 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0,
1342 candidate2);
1343 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2));
1344 SetRemoteDescriptionWithoutError(offer);
1345
1346 remote_desc = session_->remote_description();
1347 ASSERT_TRUE(remote_desc != NULL);
1348 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1349 candidates = remote_desc->candidates(kMediaContentIndex0);
1350 ASSERT_EQ(2u, candidates->count());
1351 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1352 // Username and password have be updated with the TransportInfo of the
1353 // SessionDescription, won't be equal to the original one.
1354 candidate2.set_username(candidates->at(0)->candidate().username());
1355 candidate2.set_password(candidates->at(0)->candidate().password());
1356 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate()));
1357 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index());
1358 // No need to verify the username and password.
1359 candidate1.set_username(candidates->at(1)->candidate().username());
1360 candidate1.set_password(candidates->at(1)->candidate().password());
1361 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate()));
1362
1363 // Test that the candidate is ignored if we can add the same candidate again.
1364 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
1365}
1366
1367// Test that local candidates are added to the local session description and
1368// that they are retained if the local session description is changed.
1369TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) {
1370 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001371 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372 mediastream_signaling_.SendAudioVideoStream1();
1373 CreateAndSetRemoteOfferAndLocalAnswer();
1374
1375 const SessionDescriptionInterface* local_desc = session_->local_description();
1376 const IceCandidateCollection* candidates =
1377 local_desc->candidates(kMediaContentIndex0);
1378 ASSERT_TRUE(candidates != NULL);
1379 EXPECT_EQ(0u, candidates->count());
1380
1381 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
1382
1383 local_desc = session_->local_description();
1384 candidates = local_desc->candidates(kMediaContentIndex0);
1385 ASSERT_TRUE(candidates != NULL);
1386 EXPECT_LT(0u, candidates->count());
1387 candidates = local_desc->candidates(1);
1388 ASSERT_TRUE(candidates != NULL);
1389 EXPECT_LT(0u, candidates->count());
1390
1391 // Update the session descriptions.
1392 mediastream_signaling_.SendAudioVideoStream1();
1393 CreateAndSetRemoteOfferAndLocalAnswer();
1394
1395 local_desc = session_->local_description();
1396 candidates = local_desc->candidates(kMediaContentIndex0);
1397 ASSERT_TRUE(candidates != NULL);
1398 EXPECT_LT(0u, candidates->count());
1399 candidates = local_desc->candidates(1);
1400 ASSERT_TRUE(candidates != NULL);
1401 EXPECT_LT(0u, candidates->count());
1402}
1403
1404// Test that we can set a remote session description with remote candidates.
1405TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001406 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001407
1408 cricket::Candidate candidate1;
1409 candidate1.set_component(1);
1410 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
1411 candidate1);
1412 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001413 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414
1415 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
1416 SetRemoteDescriptionWithoutError(offer);
1417
1418 const SessionDescriptionInterface* remote_desc =
1419 session_->remote_description();
1420 ASSERT_TRUE(remote_desc != NULL);
1421 ASSERT_EQ(2u, remote_desc->number_of_mediasections());
1422 const IceCandidateCollection* candidates =
1423 remote_desc->candidates(kMediaContentIndex0);
1424 ASSERT_EQ(1u, candidates->count());
1425 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index());
1426
wu@webrtc.org91053e72013-08-10 07:18:04 +00001427 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001428 SetLocalDescriptionWithoutError(answer);
1429}
1430
1431// Test that offers and answers contains ice candidates when Ice candidates have
1432// been gathered.
1433TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) {
1434 AddInterface(kClientAddr1);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001435 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001436 mediastream_signaling_.SendAudioVideoStream1();
1437 // Ice is started but candidates are not provided until SetLocalDescription
1438 // is called.
1439 EXPECT_EQ(0u, observer_.mline_0_candidates_.size());
1440 EXPECT_EQ(0u, observer_.mline_1_candidates_.size());
1441 CreateAndSetRemoteOfferAndLocalAnswer();
1442 // Wait until at least one local candidate has been collected.
1443 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(),
1444 kIceCandidatesTimeout);
1445 EXPECT_TRUE_WAIT(0u < observer_.mline_1_candidates_.size(),
1446 kIceCandidatesTimeout);
1447
1448 talk_base::scoped_ptr<SessionDescriptionInterface> local_offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001449 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001450 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
1451 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
1452 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex1) != NULL);
1453 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex1)->count());
1454
1455 SessionDescriptionInterface* remote_offer(CreateRemoteOffer());
1456 SetRemoteDescriptionWithoutError(remote_offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001457 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001458 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL);
1459 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count());
1460 ASSERT_TRUE(answer->candidates(kMediaContentIndex1) != NULL);
1461 EXPECT_LT(0u, answer->candidates(kMediaContentIndex1)->count());
1462 SetLocalDescriptionWithoutError(answer);
1463}
1464
1465// Verifies TransportProxy and media channels are created with content names
1466// present in the SessionDescription.
1467TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001468 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001469 mediastream_signaling_.SendAudioVideoStream1();
1470 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001471 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001472
1473 // CreateOffer creates session description with the content names "audio" and
1474 // "video". Goal is to modify these content names and verify transport channel
1475 // proxy in the BaseSession, as proxies are created with the content names
1476 // present in SDP.
1477 std::string sdp;
1478 EXPECT_TRUE(offer->ToString(&sdp));
1479 const std::string kAudioMid = "a=mid:audio";
1480 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
1481 const std::string kVideoMid = "a=mid:video";
1482 const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
1483
1484 // Replacing |audio| with |audio_content_name|.
1485 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
1486 kAudioMidReplaceStr.c_str(),
1487 kAudioMidReplaceStr.length(),
1488 &sdp);
1489 // Replacing |video| with |video_content_name|.
1490 talk_base::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
1491 kVideoMidReplaceStr.c_str(),
1492 kVideoMidReplaceStr.length(),
1493 &sdp);
1494
1495 SessionDescriptionInterface* modified_offer =
1496 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
1497
1498 SetRemoteDescriptionWithoutError(modified_offer);
1499
1500 SessionDescriptionInterface* answer =
wu@webrtc.org91053e72013-08-10 07:18:04 +00001501 CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502 SetLocalDescriptionWithoutError(answer);
1503
1504 EXPECT_TRUE(session_->GetTransportProxy("audio_content_name") != NULL);
1505 EXPECT_TRUE(session_->GetTransportProxy("video_content_name") != NULL);
1506 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
1507 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
1508}
1509
1510// Test that an offer contains the correct media content descriptions based on
1511// the send streams when no constraints have been set.
1512TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001513 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001515 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001516 ASSERT_TRUE(offer != NULL);
1517 const cricket::ContentInfo* content =
1518 cricket::GetFirstAudioContent(offer->description());
1519 EXPECT_TRUE(content != NULL);
1520 content = cricket::GetFirstVideoContent(offer->description());
1521 EXPECT_TRUE(content == NULL);
1522}
1523
1524// Test that an offer contains the correct media content descriptions based on
1525// the send streams when no constraints have been set.
1526TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001527 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 // Test Audio only offer.
1529 mediastream_signaling_.UseOptionsAudioOnly();
1530 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001531 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 const cricket::ContentInfo* content =
1533 cricket::GetFirstAudioContent(offer->description());
1534 EXPECT_TRUE(content != NULL);
1535 content = cricket::GetFirstVideoContent(offer->description());
1536 EXPECT_TRUE(content == NULL);
1537
1538 // Test Audio / Video offer.
1539 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001540 offer.reset(CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001541 content = cricket::GetFirstAudioContent(offer->description());
1542 EXPECT_TRUE(content != NULL);
1543 content = cricket::GetFirstVideoContent(offer->description());
1544 EXPECT_TRUE(content != NULL);
1545}
1546
1547// Test that an offer contains no media content descriptions if
1548// kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false.
1549TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001550 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551 webrtc::FakeConstraints constraints_no_receive;
1552 constraints_no_receive.SetMandatoryReceiveAudio(false);
1553 constraints_no_receive.SetMandatoryReceiveVideo(false);
1554
1555 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001556 CreateOffer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001557 ASSERT_TRUE(offer != NULL);
1558 const cricket::ContentInfo* content =
1559 cricket::GetFirstAudioContent(offer->description());
1560 EXPECT_TRUE(content == NULL);
1561 content = cricket::GetFirstVideoContent(offer->description());
1562 EXPECT_TRUE(content == NULL);
1563}
1564
1565// Test that an offer contains only audio media content descriptions if
1566// kOfferToReceiveAudio constraints are set to true.
1567TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001568 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 webrtc::FakeConstraints constraints_audio_only;
1570 constraints_audio_only.SetMandatoryReceiveAudio(true);
1571 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001572 CreateOffer(&constraints_audio_only));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573
1574 const cricket::ContentInfo* content =
1575 cricket::GetFirstAudioContent(offer->description());
1576 EXPECT_TRUE(content != NULL);
1577 content = cricket::GetFirstVideoContent(offer->description());
1578 EXPECT_TRUE(content == NULL);
1579}
1580
1581// Test that an offer contains audio and video media content descriptions if
1582// kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true.
1583TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001584 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 // Test Audio / Video offer.
1586 webrtc::FakeConstraints constraints_audio_video;
1587 constraints_audio_video.SetMandatoryReceiveAudio(true);
1588 constraints_audio_video.SetMandatoryReceiveVideo(true);
1589 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001590 CreateOffer(&constraints_audio_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 const cricket::ContentInfo* content =
1592 cricket::GetFirstAudioContent(offer->description());
1593
1594 EXPECT_TRUE(content != NULL);
1595 content = cricket::GetFirstVideoContent(offer->description());
1596 EXPECT_TRUE(content != NULL);
1597
1598 // TODO(perkj): Should the direction be set to SEND_ONLY if
1599 // The constraints is set to not receive audio or video but a track is added?
1600}
1601
1602// Test that an answer can not be created if the last remote description is not
1603// an offer.
1604TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001605 Init(NULL);
1606 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 SetLocalDescriptionWithoutError(offer);
1608 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
1609 SetRemoteDescriptionWithoutError(answer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001610 EXPECT_TRUE(CreateAnswer(NULL) == NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611}
1612
1613// Test that an answer contains the correct media content descriptions when no
1614// constraints have been set.
1615TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001616 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 // Create a remote offer with audio and video content.
1618 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1619 SetRemoteDescriptionWithoutError(offer.release());
1620 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001621 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 const cricket::ContentInfo* content =
1623 cricket::GetFirstAudioContent(answer->description());
1624 ASSERT_TRUE(content != NULL);
1625 EXPECT_FALSE(content->rejected);
1626
1627 content = cricket::GetFirstVideoContent(answer->description());
1628 ASSERT_TRUE(content != NULL);
1629 EXPECT_FALSE(content->rejected);
1630}
1631
1632// Test that an answer contains the correct media content descriptions when no
1633// constraints have been set and the offer only contain audio.
1634TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001635 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001636 // Create a remote offer with audio only.
1637 cricket::MediaSessionOptions options;
1638 options.has_audio = true;
1639 options.has_video = false;
1640 talk_base::scoped_ptr<JsepSessionDescription> offer(
1641 CreateRemoteOffer(options));
1642 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
1643 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL);
1644
1645 SetRemoteDescriptionWithoutError(offer.release());
1646 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001647 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001648 const cricket::ContentInfo* content =
1649 cricket::GetFirstAudioContent(answer->description());
1650 ASSERT_TRUE(content != NULL);
1651 EXPECT_FALSE(content->rejected);
1652
1653 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL);
1654}
1655
1656// Test that an answer contains the correct media content descriptions when no
1657// constraints have been set.
1658TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001659 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001660 // Create a remote offer with audio and video content.
1661 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1662 SetRemoteDescriptionWithoutError(offer.release());
1663 // Test with a stream with tracks.
1664 mediastream_signaling_.SendAudioVideoStream1();
1665 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001666 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001667 const cricket::ContentInfo* content =
1668 cricket::GetFirstAudioContent(answer->description());
1669 ASSERT_TRUE(content != NULL);
1670 EXPECT_FALSE(content->rejected);
1671
1672 content = cricket::GetFirstVideoContent(answer->description());
1673 ASSERT_TRUE(content != NULL);
1674 EXPECT_FALSE(content->rejected);
1675}
1676
1677// Test that an answer contains the correct media content descriptions when
1678// constraints have been set but no stream is sent.
1679TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001680 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001681 // Create a remote offer with audio and video content.
1682 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1683 SetRemoteDescriptionWithoutError(offer.release());
1684
1685 webrtc::FakeConstraints constraints_no_receive;
1686 constraints_no_receive.SetMandatoryReceiveAudio(false);
1687 constraints_no_receive.SetMandatoryReceiveVideo(false);
1688
1689 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001690 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001691 const cricket::ContentInfo* content =
1692 cricket::GetFirstAudioContent(answer->description());
1693 ASSERT_TRUE(content != NULL);
1694 EXPECT_TRUE(content->rejected);
1695
1696 content = cricket::GetFirstVideoContent(answer->description());
1697 ASSERT_TRUE(content != NULL);
1698 EXPECT_TRUE(content->rejected);
1699}
1700
1701// Test that an answer contains the correct media content descriptions when
1702// constraints have been set and streams are sent.
1703TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001704 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 // Create a remote offer with audio and video content.
1706 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1707 SetRemoteDescriptionWithoutError(offer.release());
1708
1709 webrtc::FakeConstraints constraints_no_receive;
1710 constraints_no_receive.SetMandatoryReceiveAudio(false);
1711 constraints_no_receive.SetMandatoryReceiveVideo(false);
1712
1713 // Test with a stream with tracks.
1714 mediastream_signaling_.SendAudioVideoStream1();
1715 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001716 CreateAnswer(&constraints_no_receive));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001717
1718 // TODO(perkj): Should the direction be set to SEND_ONLY?
1719 const cricket::ContentInfo* content =
1720 cricket::GetFirstAudioContent(answer->description());
1721 ASSERT_TRUE(content != NULL);
1722 EXPECT_FALSE(content->rejected);
1723
1724 // TODO(perkj): Should the direction be set to SEND_ONLY?
1725 content = cricket::GetFirstVideoContent(answer->description());
1726 ASSERT_TRUE(content != NULL);
1727 EXPECT_FALSE(content->rejected);
1728}
1729
1730TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) {
1731 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001732 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733 webrtc::FakeConstraints constraints;
1734 constraints.SetOptionalVAD(false);
1735 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001736 CreateOffer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737 const cricket::ContentInfo* content =
1738 cricket::GetFirstAudioContent(offer->description());
1739 EXPECT_TRUE(content != NULL);
1740 EXPECT_TRUE(VerifyNoCNCodecs(content));
1741}
1742
1743TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) {
1744 AddCNCodecs();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001745 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001746 // Create a remote offer with audio and video content.
1747 talk_base::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer());
1748 SetRemoteDescriptionWithoutError(offer.release());
1749
1750 webrtc::FakeConstraints constraints;
1751 constraints.SetOptionalVAD(false);
1752 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001753 CreateAnswer(&constraints));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001754 const cricket::ContentInfo* content =
1755 cricket::GetFirstAudioContent(answer->description());
1756 ASSERT_TRUE(content != NULL);
1757 EXPECT_TRUE(VerifyNoCNCodecs(content));
1758}
1759
1760// This test verifies the call setup when remote answer with audio only and
1761// later updates with video.
1762TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001763 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1765 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1766
1767 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001768 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769
1770 cricket::MediaSessionOptions options;
1771 options.has_video = false;
1772 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
1773
1774 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1775 // and answer;
1776 SetLocalDescriptionWithoutError(offer);
1777 SetRemoteDescriptionWithoutError(answer);
1778
1779 video_channel_ = media_engine_->GetVideoChannel(0);
1780 voice_channel_ = media_engine_->GetVoiceChannel(0);
1781
1782 ASSERT_TRUE(video_channel_ == NULL);
1783
1784 ASSERT_EQ(0u, voice_channel_->recv_streams().size());
1785 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1786 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id);
1787
1788 // Let the remote end update the session descriptions, with Audio and Video.
1789 mediastream_signaling_.SendAudioVideoStream2();
1790 CreateAndSetRemoteOfferAndLocalAnswer();
1791
1792 video_channel_ = media_engine_->GetVideoChannel(0);
1793 voice_channel_ = media_engine_->GetVoiceChannel(0);
1794
1795 ASSERT_TRUE(video_channel_ != NULL);
1796 ASSERT_TRUE(voice_channel_ != NULL);
1797
1798 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1799 ASSERT_EQ(1u, video_channel_->send_streams().size());
1800 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1801 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1802 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1803 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1804 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1805 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1806
1807 // Change session back to audio only.
1808 mediastream_signaling_.UseOptionsAudioOnly();
1809 CreateAndSetRemoteOfferAndLocalAnswer();
1810
1811 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1812 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1813 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1814 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1815 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1816}
1817
1818// This test verifies the call setup when remote answer with video only and
1819// later updates with audio.
1820TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001821 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL);
1823 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL);
1824 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00001825 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001826
1827 cricket::MediaSessionOptions options;
1828 options.has_audio = false;
1829 options.has_video = true;
1830 SessionDescriptionInterface* answer = CreateRemoteAnswer(
1831 offer, options, cricket::SEC_ENABLED);
1832
1833 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer
1834 // and answer.
1835 SetLocalDescriptionWithoutError(offer);
1836 SetRemoteDescriptionWithoutError(answer);
1837
1838 video_channel_ = media_engine_->GetVideoChannel(0);
1839 voice_channel_ = media_engine_->GetVoiceChannel(0);
1840
1841 ASSERT_TRUE(voice_channel_ == NULL);
1842 ASSERT_TRUE(video_channel_ != NULL);
1843
1844 EXPECT_EQ(0u, video_channel_->recv_streams().size());
1845 ASSERT_EQ(1u, video_channel_->send_streams().size());
1846 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id);
1847
1848 // Update the session descriptions, with Audio and Video.
1849 mediastream_signaling_.SendAudioVideoStream2();
1850 CreateAndSetRemoteOfferAndLocalAnswer();
1851
1852 voice_channel_ = media_engine_->GetVoiceChannel(0);
1853 ASSERT_TRUE(voice_channel_ != NULL);
1854
1855 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1856 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1857 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
1858 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
1859
1860 // Change session back to video only.
1861 mediastream_signaling_.UseOptionsVideoOnly();
1862 CreateAndSetRemoteOfferAndLocalAnswer();
1863
1864 video_channel_ = media_engine_->GetVideoChannel(0);
1865 voice_channel_ = media_engine_->GetVoiceChannel(0);
1866
1867 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1868 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
1869 ASSERT_EQ(1u, video_channel_->send_streams().size());
1870 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id);
1871}
1872
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001873TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001874 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001875 mediastream_signaling_.SendAudioVideoStream1();
1876 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001877 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878 VerifyCryptoParams(offer->description());
1879 SetRemoteDescriptionWithoutError(offer.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00001880 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881 VerifyCryptoParams(answer->description());
1882}
1883
1884TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001885 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001886 session_->set_secure_policy(cricket::SEC_DISABLED);
1887 mediastream_signaling_.SendAudioVideoStream1();
1888 scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001889 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 VerifyNoCryptoParams(offer->description(), false);
1891}
1892
1893TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001894 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001895 VerifyAnswerFromNonCryptoOffer();
1896}
1897
1898TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001899 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001900 VerifyAnswerFromCryptoOffer();
1901}
1902
1903TEST_F(WebRtcSessionTest, VerifyBundleFlagInPA) {
1904 // This test verifies BUNDLE flag in PortAllocator, if BUNDLE information in
1905 // local description is removed by the application, BUNDLE flag should be
1906 // disabled in PortAllocator. By default BUNDLE is enabled in the WebRtc.
wu@webrtc.org91053e72013-08-10 07:18:04 +00001907 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001908 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1909 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1910 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00001911 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001912 cricket::SessionDescription* offer_copy =
1913 offer->description()->Copy();
1914 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1915 JsepSessionDescription* modified_offer =
1916 new JsepSessionDescription(JsepSessionDescription::kOffer);
1917 modified_offer->Initialize(offer_copy, "1", "1");
1918
1919 SetLocalDescriptionWithoutError(modified_offer);
1920 EXPECT_FALSE(allocator_.flags() & cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1921}
1922
1923TEST_F(WebRtcSessionTest, TestDisabledBundleInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001924 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001925 mediastream_signaling_.SendAudioVideoStream1();
1926 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1927 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1928 FakeConstraints constraints;
1929 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001930 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931 SetLocalDescriptionWithoutError(offer);
1932 mediastream_signaling_.SendAudioVideoStream2();
1933 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
1934 CreateRemoteAnswer(session_->local_description()));
1935 cricket::SessionDescription* answer_copy = answer->description()->Copy();
1936 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1937 JsepSessionDescription* modified_answer =
1938 new JsepSessionDescription(JsepSessionDescription::kAnswer);
1939 modified_answer->Initialize(answer_copy, "1", "1");
1940 SetRemoteDescriptionWithoutError(modified_answer);
1941 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1942 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1943
1944 video_channel_ = media_engine_->GetVideoChannel(0);
1945 voice_channel_ = media_engine_->GetVoiceChannel(0);
1946
1947 ASSERT_EQ(1u, video_channel_->recv_streams().size());
1948 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id);
1949
1950 ASSERT_EQ(1u, voice_channel_->recv_streams().size());
1951 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id);
1952
1953 ASSERT_EQ(1u, video_channel_->send_streams().size());
1954 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id);
1955 ASSERT_EQ(1u, voice_channel_->send_streams().size());
1956 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id);
1957}
1958
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001959// This test verifies that SetLocalDescription and SetRemoteDescription fails
1960// if BUNDLE is enabled but rtcp-mux is disabled in m-lines.
1961TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001962 WebRtcSessionTest::Init(NULL);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001963 mediastream_signaling_.SendAudioVideoStream1();
1964 EXPECT_TRUE((cricket::PORTALLOCATOR_ENABLE_BUNDLE & allocator_.flags()) ==
1965 cricket::PORTALLOCATOR_ENABLE_BUNDLE);
1966 FakeConstraints constraints;
1967 constraints.SetMandatoryUseRtpMux(true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00001968 SessionDescriptionInterface* offer = CreateOffer(&constraints);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00001969 std::string offer_str;
1970 offer->ToString(&offer_str);
1971 // Disable rtcp-mux
1972 const std::string rtcp_mux = "rtcp-mux";
1973 const std::string xrtcp_mux = "xrtcp-mux";
1974 talk_base::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(),
1975 xrtcp_mux.c_str(), xrtcp_mux.length(),
1976 &offer_str);
1977 JsepSessionDescription *local_offer =
1978 new JsepSessionDescription(JsepSessionDescription::kOffer);
1979 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL));
1980 SetLocalDescriptionExpectError(kBundleWithoutRtcpMux, local_offer);
1981 JsepSessionDescription *remote_offer =
1982 new JsepSessionDescription(JsepSessionDescription::kOffer);
1983 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL));
1984 SetRemoteDescriptionExpectError(kBundleWithoutRtcpMux, remote_offer);
1985 // Trying unmodified SDP.
1986 SetLocalDescriptionWithoutError(offer);
1987}
1988
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001989TEST_F(WebRtcSessionTest, SetAudioPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00001990 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991 mediastream_signaling_.SendAudioVideoStream1();
1992 CreateAndSetRemoteOfferAndLocalAnswer();
1993 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
1994 ASSERT_TRUE(channel != NULL);
1995 ASSERT_EQ(1u, channel->recv_streams().size());
1996 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
1997 double left_vol, right_vol;
1998 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
1999 EXPECT_EQ(1, left_vol);
2000 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002001 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2002 session_->SetAudioPlayout(receive_ssrc, false, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2004 EXPECT_EQ(0, left_vol);
2005 EXPECT_EQ(0, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002006 EXPECT_EQ(0, renderer->channel_id());
2007 session_->SetAudioPlayout(receive_ssrc, true, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002008 EXPECT_TRUE(channel->GetOutputScaling(receive_ssrc, &left_vol, &right_vol));
2009 EXPECT_EQ(1, left_vol);
2010 EXPECT_EQ(1, right_vol);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002011 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012}
2013
2014TEST_F(WebRtcSessionTest, SetAudioSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002015 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 mediastream_signaling_.SendAudioVideoStream1();
2017 CreateAndSetRemoteOfferAndLocalAnswer();
2018 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2019 ASSERT_TRUE(channel != NULL);
2020 ASSERT_EQ(1u, channel->send_streams().size());
2021 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2022 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2023
2024 cricket::AudioOptions options;
2025 options.echo_cancellation.Set(true);
2026
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002027 talk_base::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer());
2028 session_->SetAudioSend(send_ssrc, false, options, renderer.get());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2030 EXPECT_FALSE(channel->options().echo_cancellation.IsSet());
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002031 EXPECT_EQ(0, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002033 session_->SetAudioSend(send_ssrc, true, options, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2035 bool value;
2036 EXPECT_TRUE(channel->options().echo_cancellation.Get(&value));
2037 EXPECT_TRUE(value);
henrike@webrtc.org1e09a712013-07-26 19:17:59 +00002038 EXPECT_EQ(-1, renderer->channel_id());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039}
2040
2041TEST_F(WebRtcSessionTest, SetVideoPlayout) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002042 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043 mediastream_signaling_.SendAudioVideoStream1();
2044 CreateAndSetRemoteOfferAndLocalAnswer();
2045 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2046 ASSERT_TRUE(channel != NULL);
2047 ASSERT_LT(0u, channel->renderers().size());
2048 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2049 ASSERT_EQ(1u, channel->recv_streams().size());
2050 uint32 receive_ssrc = channel->recv_streams()[0].first_ssrc();
2051 cricket::FakeVideoRenderer renderer;
2052 session_->SetVideoPlayout(receive_ssrc, true, &renderer);
2053 EXPECT_TRUE(channel->renderers().begin()->second == &renderer);
2054 session_->SetVideoPlayout(receive_ssrc, false, &renderer);
2055 EXPECT_TRUE(channel->renderers().begin()->second == NULL);
2056}
2057
2058TEST_F(WebRtcSessionTest, SetVideoSend) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002059 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 mediastream_signaling_.SendAudioVideoStream1();
2061 CreateAndSetRemoteOfferAndLocalAnswer();
2062 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0);
2063 ASSERT_TRUE(channel != NULL);
2064 ASSERT_EQ(1u, channel->send_streams().size());
2065 uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2066 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2067 cricket::VideoOptions* options = NULL;
2068 session_->SetVideoSend(send_ssrc, false, options);
2069 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc));
2070 session_->SetVideoSend(send_ssrc, true, options);
2071 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc));
2072}
2073
2074TEST_F(WebRtcSessionTest, CanNotInsertDtmf) {
2075 TestCanInsertDtmf(false);
2076}
2077
2078TEST_F(WebRtcSessionTest, CanInsertDtmf) {
2079 TestCanInsertDtmf(true);
2080}
2081
2082TEST_F(WebRtcSessionTest, InsertDtmf) {
2083 // Setup
wu@webrtc.org91053e72013-08-10 07:18:04 +00002084 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002085 mediastream_signaling_.SendAudioVideoStream1();
2086 CreateAndSetRemoteOfferAndLocalAnswer();
2087 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0);
2088 EXPECT_EQ(0U, channel->dtmf_info_queue().size());
2089
2090 // Insert DTMF
2091 const int expected_flags = DF_SEND;
2092 const int expected_duration = 90;
2093 session_->InsertDtmf(kAudioTrack1, 0, expected_duration);
2094 session_->InsertDtmf(kAudioTrack1, 1, expected_duration);
2095 session_->InsertDtmf(kAudioTrack1, 2, expected_duration);
2096
2097 // Verify
2098 ASSERT_EQ(3U, channel->dtmf_info_queue().size());
2099 const uint32 send_ssrc = channel->send_streams()[0].first_ssrc();
2100 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0,
2101 expected_duration, expected_flags));
2102 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1,
2103 expected_duration, expected_flags));
2104 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2,
2105 expected_duration, expected_flags));
2106}
2107
2108// This test verifies the |initiator| flag when session initiates the call.
2109TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002110 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002111 EXPECT_FALSE(session_->initiator());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002112 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002113 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2114 SetLocalDescriptionWithoutError(offer);
2115 EXPECT_TRUE(session_->initiator());
2116 SetRemoteDescriptionWithoutError(answer);
2117 EXPECT_TRUE(session_->initiator());
2118}
2119
2120// This test verifies the |initiator| flag when session receives the call.
2121TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002122 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002123 EXPECT_FALSE(session_->initiator());
2124 SessionDescriptionInterface* offer = CreateRemoteOffer();
2125 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002126 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002127
2128 EXPECT_FALSE(session_->initiator());
2129 SetLocalDescriptionWithoutError(answer);
2130 EXPECT_FALSE(session_->initiator());
2131}
2132
2133// This test verifies the ice protocol type at initiator of the call
2134// if |a=ice-options:google-ice| is present in answer.
2135TEST_F(WebRtcSessionTest, TestInitiatorGIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002136 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002137 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002138 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002139 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002140 CreateRemoteAnswer(offer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002141 SetLocalDescriptionWithoutError(offer);
2142 std::string sdp;
2143 EXPECT_TRUE(answer->ToString(&sdp));
2144 // Adding ice-options to the session level.
2145 InjectAfter("t=0 0\r\n",
2146 "a=ice-options:google-ice\r\n",
2147 &sdp);
2148 SessionDescriptionInterface* answer_with_gice =
2149 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2150 SetRemoteDescriptionWithoutError(answer_with_gice);
2151 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2152 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2153}
2154
2155// This test verifies the ice protocol type at initiator of the call
2156// if ICE RFC5245 is supported in answer.
2157TEST_F(WebRtcSessionTest, TestInitiatorIceInAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002158 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002160 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002161 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
2162 SetLocalDescriptionWithoutError(offer);
2163
2164 SetRemoteDescriptionWithoutError(answer);
2165 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2166 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2167}
2168
2169// This test verifies the ice protocol type at receiver side of the call if
2170// receiver decides to use google-ice.
2171TEST_F(WebRtcSessionTest, TestReceiverGIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002172 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002174 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002175 SetRemoteDescriptionWithoutError(offer);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002176 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002177 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002178 std::string sdp;
2179 EXPECT_TRUE(answer->ToString(&sdp));
2180 // Adding ice-options to the session level.
2181 InjectAfter("t=0 0\r\n",
2182 "a=ice-options:google-ice\r\n",
2183 &sdp);
2184 SessionDescriptionInterface* answer_with_gice =
2185 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2186 SetLocalDescriptionWithoutError(answer_with_gice);
2187 VerifyTransportType("audio", cricket::ICEPROTO_GOOGLE);
2188 VerifyTransportType("video", cricket::ICEPROTO_GOOGLE);
2189}
2190
2191// This test verifies the ice protocol type at receiver side of the call if
2192// receiver decides to use ice RFC 5245.
2193TEST_F(WebRtcSessionTest, TestReceiverIceInOffer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002194 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002195 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002196 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002197 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002198 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002199 SetLocalDescriptionWithoutError(answer);
2200 VerifyTransportType("audio", cricket::ICEPROTO_RFC5245);
2201 VerifyTransportType("video", cricket::ICEPROTO_RFC5245);
2202}
2203
2204// This test verifies the session state when ICE RFC5245 in offer and
2205// ICE google-ice in answer.
2206TEST_F(WebRtcSessionTest, TestIceOfferGIceOnlyAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002207 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002208 mediastream_signaling_.SendAudioVideoStream1();
2209 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002210 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002211 std::string offer_str;
2212 offer->ToString(&offer_str);
2213 // Disable google-ice
2214 const std::string gice_option = "google-ice";
2215 const std::string xgoogle_xice = "xgoogle-xice";
2216 talk_base::replace_substrs(gice_option.c_str(), gice_option.length(),
2217 xgoogle_xice.c_str(), xgoogle_xice.length(),
2218 &offer_str);
2219 JsepSessionDescription *ice_only_offer =
2220 new JsepSessionDescription(JsepSessionDescription::kOffer);
2221 EXPECT_TRUE((ice_only_offer)->Initialize(offer_str, NULL));
2222 SetLocalDescriptionWithoutError(ice_only_offer);
2223 std::string original_offer_sdp;
2224 EXPECT_TRUE(offer->ToString(&original_offer_sdp));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002225 SessionDescriptionInterface* pranswer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 CreateSessionDescription(JsepSessionDescription::kPrAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002227 original_offer_sdp, NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002228 SetRemoteDescriptionExpectError(kPushDownPranswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002229 pranswer_with_gice);
2230 SessionDescriptionInterface* answer_with_gice =
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002231 CreateSessionDescription(JsepSessionDescription::kAnswer,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002232 original_offer_sdp, NULL);
henrike@webrtc.org723d6832013-07-12 16:04:50 +00002233 SetRemoteDescriptionExpectError(kPushDownAnswerTDFailed,
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002234 answer_with_gice);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235}
2236
2237// Verifing local offer and remote answer have matching m-lines as per RFC 3264.
2238TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002239 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002240 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002241 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242 SetLocalDescriptionWithoutError(offer);
2243 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2244 CreateRemoteAnswer(session_->local_description()));
2245
2246 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2247 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002248 JsepSessionDescription* modified_answer =
2249 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250
2251 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2252 answer->session_id(),
2253 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002254 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002255
2256 // Modifying content names.
2257 std::string sdp;
2258 EXPECT_TRUE(answer->ToString(&sdp));
2259 const std::string kAudioMid = "a=mid:audio";
2260 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
2261
2262 // Replacing |audio| with |audio_content_name|.
2263 talk_base::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
2264 kAudioMidReplaceStr.c_str(),
2265 kAudioMidReplaceStr.length(),
2266 &sdp);
2267
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002268 SessionDescriptionInterface* modified_answer1 =
2269 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL);
2270 SetRemoteDescriptionExpectError(kMlineMismatch, modified_answer1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002271
2272 SetRemoteDescriptionWithoutError(answer.release());
2273}
2274
2275// Verifying remote offer and local answer have matching m-lines as per
2276// RFC 3264.
2277TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002278 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002279 mediastream_signaling_.SendAudioVideoStream1();
2280 SessionDescriptionInterface* offer = CreateRemoteOffer();
2281 SetRemoteDescriptionWithoutError(offer);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002282 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002283
2284 cricket::SessionDescription* answer_copy = answer->description()->Copy();
2285 answer_copy->RemoveContentByName("video");
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002286 JsepSessionDescription* modified_answer =
2287 new JsepSessionDescription(JsepSessionDescription::kAnswer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288
2289 EXPECT_TRUE(modified_answer->Initialize(answer_copy,
2290 answer->session_id(),
2291 answer->session_version()));
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002292 SetLocalDescriptionExpectError(kMlineMismatch, modified_answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002293 SetLocalDescriptionWithoutError(answer);
2294}
2295
2296// This test verifies that WebRtcSession does not start candidate allocation
2297// before SetLocalDescription is called.
2298TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002299 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002300 mediastream_signaling_.SendAudioVideoStream1();
2301 SessionDescriptionInterface* offer = CreateRemoteOffer();
2302 cricket::Candidate candidate;
2303 candidate.set_component(1);
2304 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0,
2305 candidate);
2306 EXPECT_TRUE(offer->AddCandidate(&ice_candidate));
2307 cricket::Candidate candidate1;
2308 candidate1.set_component(1);
2309 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1,
2310 candidate1);
2311 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1));
2312 SetRemoteDescriptionWithoutError(offer);
2313 ASSERT_TRUE(session_->GetTransportProxy("audio") != NULL);
2314 ASSERT_TRUE(session_->GetTransportProxy("video") != NULL);
2315
2316 // Pump for 1 second and verify that no candidates are generated.
2317 talk_base::Thread::Current()->ProcessMessages(1000);
2318 EXPECT_TRUE(observer_.mline_0_candidates_.empty());
2319 EXPECT_TRUE(observer_.mline_1_candidates_.empty());
2320
wu@webrtc.org91053e72013-08-10 07:18:04 +00002321 SessionDescriptionInterface* answer = CreateAnswer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002322 SetLocalDescriptionWithoutError(answer);
2323 EXPECT_TRUE(session_->GetTransportProxy("audio")->negotiated());
2324 EXPECT_TRUE(session_->GetTransportProxy("video")->negotiated());
2325 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout);
2326}
2327
2328// This test verifies that crypto parameter is updated in local session
2329// description as per security policy set in MediaSessionDescriptionFactory.
2330TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002331 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332 mediastream_signaling_.SendAudioVideoStream1();
2333 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002334 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002335
2336 // Making sure SetLocalDescription correctly sets crypto value in
2337 // SessionDescription object after de-serialization of sdp string. The value
2338 // will be set as per MediaSessionDescriptionFactory.
2339 std::string offer_str;
2340 offer->ToString(&offer_str);
2341 SessionDescriptionInterface* jsep_offer_str =
2342 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2343 SetLocalDescriptionWithoutError(jsep_offer_str);
2344 EXPECT_TRUE(session_->voice_channel()->secure_required());
2345 EXPECT_TRUE(session_->video_channel()->secure_required());
2346}
2347
2348// This test verifies the crypto parameter when security is disabled.
2349TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002350 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002351 mediastream_signaling_.SendAudioVideoStream1();
2352 session_->set_secure_policy(cricket::SEC_DISABLED);
2353 talk_base::scoped_ptr<SessionDescriptionInterface> offer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002354 CreateOffer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002355
2356 // Making sure SetLocalDescription correctly sets crypto value in
2357 // SessionDescription object after de-serialization of sdp string. The value
2358 // will be set as per MediaSessionDescriptionFactory.
2359 std::string offer_str;
2360 offer->ToString(&offer_str);
2361 SessionDescriptionInterface *jsep_offer_str =
2362 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL);
2363 SetLocalDescriptionWithoutError(jsep_offer_str);
2364 EXPECT_FALSE(session_->voice_channel()->secure_required());
2365 EXPECT_FALSE(session_->video_channel()->secure_required());
2366}
2367
2368// This test verifies that an answer contains new ufrag and password if an offer
2369// with new ufrag and password is received.
2370TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002371 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372 cricket::MediaSessionOptions options;
2373 options.has_audio = true;
2374 options.has_video = true;
2375 talk_base::scoped_ptr<JsepSessionDescription> offer(
2376 CreateRemoteOffer(options));
2377 SetRemoteDescriptionWithoutError(offer.release());
2378
2379 mediastream_signaling_.SendAudioVideoStream1();
2380 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002381 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002382 SetLocalDescriptionWithoutError(answer.release());
2383
2384 // Receive an offer with new ufrag and password.
2385 options.transport_options.ice_restart = true;
2386 talk_base::scoped_ptr<JsepSessionDescription> updated_offer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002387 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002388 SetRemoteDescriptionWithoutError(updated_offer1.release());
2389
2390 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer1(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002391 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002392
2393 CompareIceUfragAndPassword(updated_answer1->description(),
2394 session_->local_description()->description(),
2395 false);
2396
2397 SetLocalDescriptionWithoutError(updated_answer1.release());
wu@webrtc.org91053e72013-08-10 07:18:04 +00002398}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002399
wu@webrtc.org91053e72013-08-10 07:18:04 +00002400// This test verifies that an answer contains old ufrag and password if an offer
2401// with old ufrag and password is received.
2402TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
2403 Init(NULL);
2404 cricket::MediaSessionOptions options;
2405 options.has_audio = true;
2406 options.has_video = true;
2407 talk_base::scoped_ptr<JsepSessionDescription> offer(
2408 CreateRemoteOffer(options));
2409 SetRemoteDescriptionWithoutError(offer.release());
2410
2411 mediastream_signaling_.SendAudioVideoStream1();
2412 talk_base::scoped_ptr<SessionDescriptionInterface> answer(
2413 CreateAnswer(NULL));
2414 SetLocalDescriptionWithoutError(answer.release());
2415
2416 // Receive an offer without changed ufrag or password.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002417 options.transport_options.ice_restart = false;
2418 talk_base::scoped_ptr<JsepSessionDescription> updated_offer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002419 CreateRemoteOffer(options, session_->remote_description()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002420 SetRemoteDescriptionWithoutError(updated_offer2.release());
2421
2422 talk_base::scoped_ptr<SessionDescriptionInterface> updated_answer2(
wu@webrtc.org91053e72013-08-10 07:18:04 +00002423 CreateAnswer(NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002424
2425 CompareIceUfragAndPassword(updated_answer2->description(),
2426 session_->local_description()->description(),
2427 true);
2428
2429 SetLocalDescriptionWithoutError(updated_answer2.release());
2430}
2431
2432TEST_F(WebRtcSessionTest, TestSessionContentError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002433 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002434 mediastream_signaling_.SendAudioVideoStream1();
wu@webrtc.org91053e72013-08-10 07:18:04 +00002435 SessionDescriptionInterface* offer = CreateOffer(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002436 const std::string session_id_orig = offer->session_id();
2437 const std::string session_version_orig = offer->session_version();
2438 SetLocalDescriptionWithoutError(offer);
2439
2440 video_channel_ = media_engine_->GetVideoChannel(0);
2441 video_channel_->set_fail_set_send_codecs(true);
2442
2443 mediastream_signaling_.SendAudioVideoStream2();
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002444 SessionDescriptionInterface* answer =
2445 CreateRemoteAnswer(session_->local_description());
2446 SetRemoteDescriptionExpectError("ERROR_CONTENT", answer);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002447}
2448
2449// Runs the loopback call test with BUNDLE and STUN disabled.
2450TEST_F(WebRtcSessionTest, TestIceStatesBasic) {
2451 // Lets try with only UDP ports.
2452 allocator_.set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
2453 cricket::PORTALLOCATOR_DISABLE_TCP |
2454 cricket::PORTALLOCATOR_DISABLE_STUN |
2455 cricket::PORTALLOCATOR_DISABLE_RELAY);
2456 TestLoopbackCall();
2457}
2458
2459// Regression-test for a crash which should have been an error.
2460TEST_F(WebRtcSessionTest, TestNoStateTransitionPendingError) {
wu@webrtc.org91053e72013-08-10 07:18:04 +00002461 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002462 cricket::MediaSessionOptions options;
2463 options.has_audio = true;
2464 options.has_video = true;
2465
2466 session_->SetError(cricket::BaseSession::ERROR_CONTENT);
2467 SessionDescriptionInterface* offer = CreateRemoteOffer(options);
2468 SessionDescriptionInterface* answer =
2469 CreateRemoteAnswer(offer, options);
2470 SetRemoteDescriptionExpectError(kSessionError, offer);
2471 SetLocalDescriptionExpectError(kSessionError, answer);
2472 // Not crashing is our success.
2473}
2474
2475TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
2476 constraints_.reset(new FakeConstraints());
2477 constraints_->AddOptional(
2478 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002479 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002480
2481 SetLocalDescriptionWithDataChannel();
2482 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2483}
2484
2485TEST_F(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) {
2486 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2487
2488 constraints_.reset(new FakeConstraints());
2489 constraints_->AddOptional(
2490 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true);
2491 constraints_->AddOptional(
2492 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2493 constraints_->AddOptional(
2494 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002495 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002496
2497 SetLocalDescriptionWithDataChannel();
2498 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type());
2499}
2500
2501TEST_F(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) {
2502 constraints_.reset(new FakeConstraints());
2503 constraints_->AddOptional(
2504 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002505 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002506
2507 SetLocalDescriptionWithDataChannel();
2508 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type());
2509}
2510
2511TEST_F(WebRtcSessionTest, TestSctpDataChannelWithDtls) {
2512 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2513
2514 constraints_.reset(new FakeConstraints());
2515 constraints_->AddOptional(
2516 webrtc::MediaConstraintsInterface::kEnableSctpDataChannels, true);
2517 constraints_->AddOptional(
2518 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, true);
wu@webrtc.org91053e72013-08-10 07:18:04 +00002519 Init(NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002520
2521 SetLocalDescriptionWithDataChannel();
2522 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
2523}
wu@webrtc.org91053e72013-08-10 07:18:04 +00002524
2525// Verifies that CreateOffer succeeds when CreateOffer is called before async
2526// identity generation is finished.
2527TEST_F(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) {
2528 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2529 InitWithAsyncDtls(false);
2530
2531 EXPECT_TRUE(session_->waiting_for_identity());
2532 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2533 EXPECT_TRUE(offer != NULL);
2534}
2535
2536// Verifies that CreateAnswer succeeds when CreateOffer is called before async
2537// identity generation is finished.
2538TEST_F(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) {
2539 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2540 InitWithAsyncDtls(false);
2541
2542 cricket::MediaSessionOptions options;
2543 scoped_ptr<JsepSessionDescription> offer(
2544 CreateRemoteOffer(options, cricket::SEC_REQUIRED));
2545 ASSERT_TRUE(offer.get() != NULL);
2546 SetRemoteDescriptionWithoutError(offer.release());
2547
2548 talk_base::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL));
2549 EXPECT_TRUE(answer != NULL);
2550}
2551
2552// Verifies that CreateOffer succeeds when CreateOffer is called after async
2553// identity generation is finished.
2554TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) {
2555 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2556 InitWithAsyncDtls(false);
2557
2558 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2559 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2560 EXPECT_TRUE(offer != NULL);
2561}
2562
2563// Verifies that CreateOffer fails when CreateOffer is called after async
2564// identity generation fails.
2565TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) {
2566 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2567 InitWithAsyncDtls(true);
2568
2569 EXPECT_TRUE_WAIT(!session_->waiting_for_identity(), 1000);
2570 talk_base::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer(NULL));
2571 EXPECT_TRUE(offer == NULL);
2572}
2573
2574// Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made
2575// before async identity generation is finished.
2576TEST_F(WebRtcSessionTest,
2577 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) {
2578 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2579 VerifyMultipleAsyncCreateDescription(
2580 true, CreateSessionDescriptionRequest::kOffer);
2581}
2582
2583// Verifies that CreateOffer fails when Multiple CreateOffer calls are made
2584// before async identity generation fails.
2585TEST_F(WebRtcSessionTest,
2586 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) {
2587 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2588 VerifyMultipleAsyncCreateDescription(
2589 false, CreateSessionDescriptionRequest::kOffer);
2590}
2591
2592// Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made
2593// before async identity generation is finished.
2594TEST_F(WebRtcSessionTest,
2595 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) {
2596 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2597 VerifyMultipleAsyncCreateDescription(
2598 true, CreateSessionDescriptionRequest::kAnswer);
2599}
2600
2601// Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made
2602// before async identity generation fails.
2603TEST_F(WebRtcSessionTest,
2604 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) {
2605 MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
2606 VerifyMultipleAsyncCreateDescription(
2607 false, CreateSessionDescriptionRequest::kAnswer);
2608}
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002609// TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test
2610// currently fails because upon disconnection and reconnection OnIceComplete is
2611// called more than once without returning to IceGatheringGathering.